双向链表:
传统链表沿着链表的反向遍历是很困难的,为了解决这一问题------引入双向链表
双向链表的链结点有两个指向其他节点的引用。一个指向前驱,一个指向后继。
图解:
双向链表的头插法:分为两种情况
a.头结点为空
this.head=node;
this.last=node;
//头结点和尾结点均为node
b.头结点不为空
node.next=this.head;//node的下一个结点为head
this.head.prev=node;//head的前驱为node
this.head=node;//头结点指向node 当前头结点为node
代码实现:
public void addFirst(int data) {
Node node = new Node(data);
if (this.head == null) {//头结点为空
this.head = node;
this.last = node;
} else {//头结点不为空
node.next = this.head;
this.head.prev = node;
this.head = node;
}
}
双向链表的尾删法:
与头插法类似。
头结点不为空时:
this.last.next=node;//尾结点的下一个结点为node
node.prev=this.last;//node结点的前驱是尾结点
this.last=node;//尾结点指向node结点 即当前尾结点为node
代码实现:
public void addLast(int data) {
Node node = new Node(data);
if (this.head == null) {
this.head = node;
this.last = node;
} else {
this.last.next = node;
node.prev = this.last;
this.last = node;
}
}
双向链表的任意位置插入数:
思想:
1.合法性检查
checkIndex(index);
2.index-1位置的下标
private Node searchIndex(int index) {
checkIndex(index);
Node cur = this.head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
return cur;
}
3.分情况
a.插入位置为第一个数(头插法)
if(index==0){
addFirst(data);
return true;
}
b.插入位置为最后一个数(尾插法)
if(index==this.length){
addLast(data);
return true;}
c.插入位置为中间的数
Node node=new Node(data);//定义结点node 数据域为data
Node cur=searchIndex(index);//查找index-1位置的下标
node.next=cur;//node结点的下一个结点为cur
node.prev=cur.prev;//node的前驱为cur的前驱
node.next.prev=node;//node的下一个结点的前驱为node
node.prev.next=node;//node前驱的下一个结点为node
1.合法性检查:
private void checkIndex(int index) {
if (index < 0 || index > this.getLength()) {
throw new NullPointerException("Index错误");
}
}
2.插入函数代码:
public boolean addindex(int index, int data) {
{
checkIndex(index);
if (index == 0) {
addFirst(data);
return true;
}
if (index == this.getLength()) {
addLast(data);
return true;
}
Node node = new Node(data);
Node cur = searchIndex(index);
node.next = cur;
node.prev = cur.prev;
node.next.prev = node;
node.prev.next = node;
return true;
}
}