双向链表是一种更复杂的链表结构,与单向链表类似,但是每个节点除了有一个指向下一个节点的指针外,还有一个指向前一个节点的指针。这种双向链接使得在列表中向前和向后遍历变得更加方便。
下面是如何使用Java实现一个基本的双向链表的步骤:
定义双向链表节点
首先,定义双向链表的节点类,每个节点都有一个值,一个指向前一个节点的指针(prev),和一个指向下一个节点的指针(next)。
public class DoublyListNode {
int data;
DoublyListNode prev;
DoublyListNode next;
public DoublyListNode(int data) {
this.data = data;
this.prev = null;
this.next = null;
}
}
实现双向链表
接着,我们可以创建一个双向链表类来管理这些节点:
public class DoublyLinkedList {
private DoublyListNode head;
private DoublyListNode tail;
public DoublyLinkedList() {
head = null;
tail = null;
}
// 在链表头部添加节点
public void prepend(int data) {
DoublyListNode newNode = new DoublyListNode(data);
if (head == null) {
head = newNode;
tail = newNode;
} else {
head.prev = newNode;
newNode.next = head;
head = newNode;
}
}
// 在链表尾部添加节点
public void append(int data) {
DoublyListNode newNode = new DoublyListNode(data);
if (tail == null) {
head = newNode;
tail = newNode;
} else {
tail.next = newNode;
newNode.prev = tail;
tail = newNode;
}
}
// 删除链表中具有特定值的节点
public void delete(int data) {
if (head == null) return;
if (head.data == data) {
head = head.next;
if (head != null) {
head.prev = null;
} else {
tail = null;
}
return;
}
DoublyListNode current = head;
while (current != null && current.data != data) {
current = current.next;
}
if (current == null) return;
if (current.next != null) {
current.next.prev = current.prev;
} else {
tail = current.prev;
}
if (current.prev != null) {
current.prev.next = current.next;
}
}
// 打印链表从头到尾
public void printForward() {
DoublyListNode current = head;
while (current != null) {
System.out.print(current.data + " <-> ");
current = current.next;
}
System.out.println("null");
}
// 打印链表从尾到头
public void printBackward() {
DoublyListNode current = tail;
while (current != null) {
System.out.print(current.data + " <-> ");
current = current.prev;
}
System.out.println("null");
}
}
使用双向链表
现在我们可以创建一个双向链表实例,在链表中添加和删除节点,并打印链表:
public class Main {
public static void main(String[] args) {
DoublyLinkedList list = new DoublyLinkedList();
// 在链表头部添加数据
list.prepend(3);
list.prepend(2);
list.prepend(1);
// 在链表尾部添加数据
list.append(4);
list.append(5);
// 打印链表(正向)
list.printForward(); // 输出: 1 <-> 2 <-> 3 <-> 4 <-> 5 <-> null
// 打印链表(反向)
list.printBackward(); // 输出: 5 <-> 4 <-> 3 <-> 2 <-> 1 <-> null
// 删除链表中的一个节点
list.delete(3);
// 再次打印链表
list.printForward(); // 输出: 1 <-> 2 <-> 4 <-> 5 <-> null
}
}
在这个示例中,我们定义了双向链表节点DoublyListNode
,它具有一个整数数据字段,一个指向前一个节点的指针prev
和一个指向下一个节点的指针next
。DoublyLinkedList
类管理一个双向链表,包括在头部和尾部添加节点,以及删除具有特定值的节点的操作。
总结
双向链表相比单向链表,由于每个节点都有两个指针,增加了一些内存开销,但也提供了向前和向后遍历的便利性。这种数据结构适用于需要频繁进行双向遍历或在列表中间进行插入和删除操作的场景。掌握双向链表的实现和操作是理解更复杂数据结构和算法的基础。