双向链表
双向链表我们可以从头到尾查找,也可以从尾到头查找。
双向链表图如下:
1、双向链表结点类
class Node<E>{
E data;
Node<E> prev;
Node<E> next;
public Node(E data, Node<E> prev, Node<E> next) {
this.data = data;
this.prev = prev;
this.next = next;
}
}
2、添加到尾结点的方法
public void linkLast(Object e){
// 用临时变量 last 保存 head 结点
final Node<Object> last = tail;
// 创建一个新的结点,让他的 prev 指针指向 last,next 指针指向 null 结点
final Node<Object> newNode = new Node<>(e, last, null);
// 让 tail 指向新的结点
tail = newNode;
// 如果之前的 last 为空,说明之前链表是空的,让 head 和 tail 同时指向新结点即可
if (last == null)
head = newNode;
else // 如果之前链表不为空,让之前 last 结点的 next 指向新的结点
last.next = newNode;
size++;
}
3、添加到头结点的方法
public void linkFirst(Object e) {
// 用临时变量 firt 保存 head 结点
final Node<Object> first = head;
// 创建一个新的结点,让他的 prev 指针指向 null,next指针指向head结点
final Node<Object> newNode = new Node<>(e, null, first);
// 让 head 指向新的结点
head = newNode;
// 如果之前的 first 为空,说明之前链表是空的,让 head 和 tail 同时指向新结点即可
if (first == null)
tail = newNode;
else // 如果之前链表不为空,让之前 first 结点的 prev 指向新的结点
first.prev = newNode;
size++;
}
4、添加到指定结点之前的方法
public void linkBefore(Object e, Node<Object> node) {
// 用临时变量 nodeprev 保存 node 结点前一个结点
final Node<Object> nodeprev = node.prev;
// 创建一个新结点,让他的 prev 指针指向 nodeprev,next 指针指向 node
final Node<Object> newNode = new Node<>(e, nodeprev, node);
// 让 node 的 next 指针指向新结点
node.prev = newNode;
// 如果之前 node 结点前一个结点为空,说明之前 node 是头结点,让 head 指向新结点
if (nodeprev == null)
head = newNode;
else // 如果之前 node 结点前一个结点不为空,让 node 结点前一个结点指向新结点
nodeprev.next = newNode;
size++;
}
5、删除链表的尾结点的方法
public Object unlinkLast(Node<Object> last) {
// 用临时变量 element 保存 last 结点的数据
final Object element = last.data;
// 创建一个新结点,指向 last 的前一个结点
final Node<Object> prev = last.prev;
// 将 last 结点的数据和前一个指针指向 null
last.data = null;
last.prev = null;
// 尾结点指向 prev
tail = prev;
// 如果只有一个结点,把尾结点删除,相当于把链表清空了
if (prev == null)
head = null;
else // 如果不止有一个结点,把 prev 的 next 指向 null
prev.next = null;
size--;
// 返回删除结点的数据
return element;
}
6、删除链表的头结点的方法
public Object unlinkFirst(Node<Object> first) {
// 用临时变量 element 保存 first 结点的数据
final Object element = first.data;
// 创建一个新结点,指向 first 的下一个结点
final Node<Object> nest = first.next;
// 将 first 结点的数据和下一个指针指向 null
first.data = null;
first.next = null;
// 头结点指向 prev
head = nest;
// 如果只有一个结点,把头结点删除,相当于把链表清空了
if (nest == null)
tail = null;
else // 如果不止有一个结点,把 next 的 prev 指向 null
nest.prev = null;
size--;
// 返回删除结点的数据
return element;
}
7、删除链表的中间结点的方法
public Object unlink(Node<Object> x) {
// 用临时变量 element 保存 x 结点的数据
final Object element = x.data;
// 创建一个新结点,指向 x 的前一个结点
final Node<Object> prev = x.prev;
// 创建一个新结点,指向 x 的下一个结点
final Node<Object> next = x.next;
// 前一个结点是空
if (prev == null) {
head = next;
} else { // 前一个结点不为空时,prev 的 next 指针指向 next,将 x 的 prev 置空
prev.next = next;
x.prev = null;
}
// 后一个结点是空
if (next == null) {
tail = null;
} else { // 后一个结点不为空时,next 的 prev 指针指向 prev,将 x 的 next 置空
next.prev = prev;
x.next = null;
}
// 将 x 的 data 置空
x.data = null;
size--;
// 返回删除结点的数据
return element;
}
完整代码
class Node<E>{
E data;
Node<E> prev;
Node<E> next;
public Node() {
}
public Node(E data, Node<E> prev, Node<E> next) {
this.data = data;
this.prev = prev;
this.next = next;
}
}
public class MyLinkedList {
Node<Object> tail = null;
Node<Object> head = null;
static int size = 0;
public MyLinkedList() {
}
public MyLinkedList(Node<Object> tail, Node<Object> head) {
this.tail = tail;
this.head = head;
}
// 添加到尾结点的方法
public void linkLast(Object e){
// 用临时变量 last 保存 head 结点
final Node<Object> last = tail;
// 创建一个新的结点,让他的 prev 指针指向 last,next 指针指向 null 结点
final Node<Object> newNode = new Node<>(e, last, null);
// 让 tail 指向新的结点
tail = newNode;
// 如果之前的 last 为空,说明之前链表是空的,让 head 和 tail 同时指向新结点即可
if (last == null)
head = newNode;
else // 如果之前链表不为空,让之前 last 结点的 next 指向新的结点
last.next = newNode;
size++;
}
// 添加到头结点的方法
public void linkFirst(Object e) {
// 用临时变量 firt 保存 head 结点
final Node<Object> first = head;
// 创建一个新的结点,让他的 prev 指针指向 null,next 指针指向 head 结点
final Node<Object> newNode = new Node<>(e, null, first);
// 让 head 指向新的结点
head = newNode;
// 如果之前的 first 为空,说明之前链表是空的,让 head 和 tail 同时指向新结点即可
if (first == null)
tail = newNode;
else // 如果之前链表不为空,让之前 first 结点的 prev 指向新的结点
first.prev = newNode;
size++;
}
// 添加到指定结点之前的方法
public void linkBefore(Object e, Node<Object> node) {
// 用临时变量 nodeprev 保存 node 结点前一个结点
final Node<Object> nodeprev = node.prev;
// 创建一个新结点,让他的 prev 指针指向 nodeprev,next 指针指向 node
final Node<Object> newNode = new Node<>(e, nodeprev, node);
// 让 node 的 next 指针指向新结点
node.prev = newNode;
// 如果之前 node 结点前一个结点为空,说明之前 node 是头结点,让 head 指向新结点
if (nodeprev == null)
head = newNode;
else // 如果之前 node 结点前一个结点不为空,让 node 结点前一个结点指向新结点
nodeprev.next = newNode;
size++;
}
// 删除链表的尾结点的方法
public Object unlinkLast(Node<Object> last) {
// 用临时变量 element 保存 last 结点的数据
final Object element = last.data;
// 创建一个新结点,指向 last 的前一个结点
final Node<Object> prev = last.prev;
// 将 last 结点的数据和前一个指针指向 null
last.data = null;
last.prev = null;
// 尾结点指向 prev
tail = prev;
// 如果只有一个结点,把尾结点删除,相当于把链表清空了
if (prev == null)
head = null;
else // 如果不止有一个结点,把 prev 的 next 指向 null
prev.next = null;
size--;
// 返回删除结点的数据
return element;
}
// 删除链表的头结点的方法
public Object unlinkFirst(Node<Object> first) {
// 用临时变量 element 保存 first 结点的数据
final Object element = first.data;
// 创建一个新结点,指向 first 的下一个结点
final Node<Object> nest = first.next;
// 将 first 结点的数据和下一个指针指向 null
first.data = null;
first.next = null;
// 头结点指向 prev
head = nest;
// 如果只有一个结点,把头结点删除,相当于把链表清空了
if (nest == null)
tail = null;
else // 如果不止有一个结点,把 next 的 prev 指向 null
nest.prev = null;
size--;
// 返回删除结点的数据
return element;
}
// 删除链表的中间结点的方法
public Object unlink(Node<Object> x) {
// 用临时变量 element 保存 x 结点的数据
final Object element = x.data;
// 创建一个新结点,指向 x 的前一个结点
final Node<Object> prev = x.prev;
// 创建一个新结点,指向 x 的下一个结点
final Node<Object> next = x.next;
// 前一个结点是空
if (prev == null) {
head = next;
} else { // 前一个结点不为空时,prev 的 next 指针指向 next,将 x 的 prev 置空
prev.next = next;
x.prev = null;
}
// 后一个结点是空
if (next == null) {
tail = null;
} else { // 后一个结点不为空时,next 的 prev 指针指向 prev,将 x 的 next 置空
next.prev = prev;
x.next = null;
}
// 将 x 的 data 置空
x.data = null;
size--;
// 返回删除结点的数据
return element;
}
}
测试一下
public class Test {
static MyLinkedList myLinkedList = new MyLinkedList();
public static void main(String[] args) {
myLinkedList.linkFirst(1);
show();
myLinkedList.linkLast(2);
myLinkedList.linkLast(3);
show();
myLinkedList.linkBefore(4, myLinkedList.head);
show();
System.out.println("删除链表的中间结点: " + myLinkedList.unlink(myLinkedList.head.next));
show();
System.out.println("删除链表的尾结点: " + myLinkedList.unlinkLast(myLinkedList.tail));
show();
System.out.println("删除链表的头结点: " + myLinkedList.unlinkFirst(myLinkedList.head));
show();
}
public static void show() {
Node<Object> node = myLinkedList.head;
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
System.out.println();
}
}
运行结果如下
1
1 2 3
4 1 2 3
删除链表的中间结点: 1
4 2 3
删除链表的尾结点: 3
4 2
删除链表的头结点: 4
2