双向链表的实现
1 定义
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表
2 基本元素
链表头 First
链表尾 Last
节点 Node
节点中数据域 data
节点中指针域 next
节点中指针域 prev
3 基本操作
表头插入 insertFirst
表尾插入 insertLast
指定特定值的节点之后插入 insertAfter
表头删除 deleteFirst
表尾删除 deleteLast
4 基本思路
insertFirst
添加第一个结点时
头结点和尾结点均指向新结点
first = newNode
last = newNode
添加新结点时
(1) 头结点指向新结点 first = newNode
(2) 新结点的next指向原有头结点 newNode.next = first
(3) 原有头结点的prev指向新结点 first.prev = newNode
(4) 尾结点指向原头结点,保持不变
代码实现
public void insertFirst(int data){
Node newNode = new Node(data);
if (isEmpty()){
last = newNode;
}else {
//将原结点的前指针同新结点相连
first.prev = newNode;
}
newNode.next = first;
first = newNode;
}
insertLast
添加第一个结点时
头结点和尾结点均指向新结点
first = newNode
last = newNode
新结点的prev指向null
添加新结点时
(1)头结点不变
(2)尾结点指向新结点 last = newNode
(3)原尾结点的next指向新结点 last.next = newNode
(4)新结点的prev指向原尾结点 newNode.prev = last
代码实现
public void insertLast(int data){
Node newNode = new Node(data);
if (isEmpty()){
first = newNode;
}else {
//将原结点的后指针同新结点相连
last.next = newNode;
newNode.prev = last;
}
last = newNode;
}
insertAfter
先找到当前结点
代码实现
public Node find(int data){
Node current = first;
while (current.data != data){
if (current.next == null){
return null;
}else {
current = current.next;
}
}
return current;
}
要插入结点为最后一个
(1) 尾结点指向新结点 last = newNode
(2) 当前结点next指向新结点 current.next = newNode
(3) 新结点的prev指向当前结点 newNode.prev = current
(4) 新结点的next指向null newNode.next = null
要插入结点为中间结点
(1) 头尾结点保持不变
(2) 当前结点的next指向指向新结点 current.next = newNode
(3) 新结点的prev指向当前结点 newNode.prev = current
(4) 新结点的next指向当前结点的下一结点 newNode.next = current.next
(5) 当前结点下一结点的prev指向新结点 current.next.prev = newNode
代码实现
public void insertAfter(int targetData, int newData){
Node current = find(targetData);
Node newNode = new Node(newData);
if (current != null){
if (current == last){
last = newNode;
newNode.next = null;
}else {
newNode.next = current.next;
current.next.prev = newNode;
}
current.next = newNode;
newNode.prev = current;
}
}
deleteFirst
只有一个结点
(1) 头尾结点均为null first,last = null
有多个结点
(1) 头结点指向原头结点的下一结点 first = first.next
(2) 原头结点的下一结点prev为null first.next.prev = null
代码实现
public int deleteFirst(){
int temp = first.data;
if (first.next == null){
last = null;
}else {
first.next.prev = null;
}
first = first.next;
return temp;
}
deleteLast
只有一个结点
(1) 头尾结点均为null first,last = null
有多个结点
(1) 尾结点指向原尾结点的上一结点 last = last.prev
(2) 原尾结点上一结点的next指向null last.prev.next = null
代码实现
public int deleteLast(){
int temp = first.data;
if (first.next == null){
first = null;
}else {
last.prev.next = null;
}
last = last.prev;
return temp;
}
deleteKey
被删除的是第一个结点
(1)头结点指向当前结点下一结点 first = current.next
(2)当前结点下一结点的prev为null,current.next.prev = null 被删除的是最后一个结点
(1)尾结点指向当前结点上一结点,last = current.prev
(2)当前结点上一结点的next为null, current.prev.next = null 被删除的是中间结点
(1) 尾结点指向当前结点下一结点 last = current.next
(2) 当前结点上一结点的next指向当前结点的下一结点 current.prev.next = current.next
(3) 当前结点下一结点的prev指向当前结点的上一结点 current.next.prev = current.prev
代码实现
public int deleteKey(int data){
Node current = find(data);
if (current != null){
if (current == first){
first = current.next;
}else {
current.prev.next = current.next;
}
if (current == last){
last = current.prev;
}else {
current.next.prev = current.prev;
}
return current.data;
}
return 0;
}