双向链表就是有两个指针域,一个指向前一项,一个指向后一项,单向链表只可以正向遍历,而双向链表不但可以正向遍历,而且可以反向遍历。
节点类
class Entry {
private int data;
private Entry pre;
private Entry next;
public Entry() {
this(0,null,null);
}
public Entry(int data, Entry pre, Entry next) {
this.data = data;
this.pre = pre;
this.next = next;
}
}
节点类是双向链表类的内部类
双向链表类
public class DoubleLinkedList {
//头结点
private Entry head;
//初始化头结点
public DoubleLinkedList() {
head = new Entry();
}
}
相比于单向链表的头插法,双向链表由于多了指针域,所以维护起来会稍微复杂一点。
插入分为四步
为了避免在修改指针域时出现的混乱,所以我们从要插入的节点node开始修改,先修改node的next域,再修改node的pre域,然后是下一个节点的pre域,head节点的next域。
node.next = head.next;
node.pre = head;
if(node.next != null)
node.next.pre = node;
head.next = node;
看一下代码实现:
public void insertHead (int data) {
Entry node = new Entry(data, null, null);
node.next = head.next;
node.pre = head;
if(node.next != null) {
node.next.pre = node;
}
head.next = node;
}
因为双向链表不存在丢失节点的问题, 我们也可以交换1,2或者3,4的顺序
可以在初始化的时候就做指针的连接,这样写起来会更简洁一点。
public void insertHead (int data) {
Entry node = new Entry(data, head, head.next);
if(node.next != null) {
node.next.pre = node;
}
head.next = node;
}
尾插法的思路和单链表相同,先找到尾结点,然后把新节点插入到尾节点中即可。
public void insertTail (int data) {
//找到尾节点
Entry last = head;
while(last.next != null) {
last = last.next;
}
//插入尾结点后面,修改尾结点的next,修改新节点的pre
last.next = new Entry(data,last,null);
}
cur.pre.next = cur.next;
if(cur.next != null)
cur.next.pre = cur.pre;
cur.pre = null;
cur.next = null;
代码实现:
public void remove (int data) {
//找到待删除节点
Entry cur = head.next;
while(cur != null) {
if(cur.data == data) {
//找到进行删除
cur.pre.next = cur.next;
if(cur.next != null) {
cur.next.pre = cur.pre;
}
//置空
cur.pre = null;
cur.next = null;
return;
}
cur = cur.next;
}
}