Java数据结构之双向链表
⚡️前言⚡️
本笔记针对无头双向链表的实现来展开,在阅读该笔记时,建议读者结合博主的单链表笔记一起阅读,两者多有相似之处,结合阅读便于理解总结😇
📍内容导读📍
双向链表概述
🍓节点类及链表头尾的建立
class Node {
public int data;//一个节点存在三个区域
public Node prev;
public Node next;
public Node(int data) {//构造方法用于初始化实例对象
this.data = data;
}
}
public class MyLinkedList {
public Node head;
public Node tail;
public void addFirst(int data);
//1.头插法
public void addLast(int data);
//2.尾插法
public void display();
//3.打印链表
public boolean contains(int key);
//4.查找是否包含关键字key是否在单链表当中
public int size();
//5.求链表长度
public void addIndex(int index,int data);
//6.任意位置插入,第一个数据节点为0号下标
public void remove(int key);
//7.删除第一次出现关键字为key的节点
public void removeAllKey(int key);
//8.删除所有值为key的节点
public void clear();
//9.清空链表
}
以下即为双向链表的各接口的实现
🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍐 🍍 🍅 🏀 💡 🔑
🍉1.头插法
public void addFirst(int data) {
Node node=new Node(data);//将data的值new为一个节点
if (this.head == null) {//第一次插入
this.head=node;//头尾节点都指向该节点
this.tail=node;
}else {
node.next=this.head;//完成连接
this.head.prev=node;//改变域值
this.head=node;//头节点前移
}
}
🍉2.尾插法
public void addLast(int data) {
Node node=new Node(data);
if(this.head==null) {
this.head=node;
this.tail=node;
}else {
this.tail.next=node;//续尾
node.prev=this.tail;//变值
this.tail=node;//移尾
}
}
🍉3.打印链表
public void display() {
Node cur=this.head;
while(cur != null) {
System.out.print(cur.data+" ");
cur=cur.next;
}
System.out.println();
}
🍉4.查找是否包含关键字
public boolean contains(int key) {
Node cur=this.head;
while(cur!=null) {
if(cur.data==key)
return true;
cur=cur.next;
}
return false;
}
🍉5.求链表长度
public int size() {
int a=0;
Node cur=this.head;
while(cur!=null) {
a++;
cur=cur.next;
}
return a;
}
🍉6.任意位置(index)插入
private void checkIndex(int index) {//判断index位置合法性
if(index<0||index>this.size()) {
throw new RuntimeException("index位置不合法");
}
}
private Node searchIndex(int index) {//查找插入的位置
Node cur=this.head;
int a=0;
while(a!=index) {
a++;
cur=cur.next;
}
return cur;
}
public void addIndex(int index,int data) {
checkIndex(index);
if(index==0) {//头插
this.addFirst(data);
return;
}
if(index==this.size()) {//尾插
this.addLast(data);
return;
}
Node node=new Node(data);//实例化node节点
Node cur=searchIndex(index);//cur存储index位置节点
node.next=cur;//左边四步完成连接过程,先对node中的值改变对原链表无影响
node.prev=cur.prev;
cur.prev.next=node;//然后连接前后
cur.prev=node;
}
🍉7.删除第一次出现关键字为key的节点
public void remove(int key) {
Node cur=this.head;
while(cur!=null) {
if(cur.data==key) {//如果找到关键字key
if(cur==this.head) {//头节点的data为key
this.head=cur.next;//头节点后移完成头节点删除
if(this.head!=null)//防止空指针异常
this.head.prev=null;
}else {//中间找到key
cur.prev.next=cur.next;
if(cur.next!=null)
cur.next.prev=cur.prev;
else//如果cur.next==null,尾节点即为所需删除节点
this.tail=cur.prev;
}
break;//完成删除后跳出循环
}
cur=cur.next;//如果没有进if语句中,cur继续往后遍历
}
}
🍉8.删除所有值为key的节点
public void remove(int key) {
Node cur=this.head;
while(cur!=null) {
if(cur.data==key) {//如果找到关键字key
if(cur==this.head) {//头节点的data为key
this.head=cur.next;//头节点后移完成头节点删除
if(this.head!=null)//防止空指针异常
this.head.prev=null;
}else {//中间找到key
cur.prev.next=cur.next;
if(cur.next!=null)
cur.next.prev=cur.prev;
else//如果cur.next==null,尾节点即为所需删除节点
this.tail=cur.prev;
}
}
cur=cur.next;//如果没有进if语句中,cur继续往后遍历
}
}
🍉9.清空链表
public void clear() {//完成遍历,所有都置为空,则内存被收回
while (this.head!=null) {
Node cur=this.head.next;
this.head.prev=null;
this.head.next=null;
this.head=cur;
}
this.tail=null;
}
⚡️最后的话⚡️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁