循环链表是一种链表,其中最后一个节点指向第一个节点,形成一个环。循环链表可以是单向的也可以是双向的。在循环链表中,不存在任何节点的下一个节点为空,这使得从列表的任何点开始都可以轻松地遍历整个链表。由于循环链表的特性,它常用于需要周期重复访问列表的场景,例如轮转调度算法。
实现单向循环链表
首先,定义链表的节点类。和单向链表类似,循环链表的节点包含数据域和指向下一个节点的指针。
public class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
// 在循环链表中,初始化时将next指向自己,形成循环
this.next = this;
}
}
接下来,实现循环链表的基本操作:
public class CircularLinkedList {
private ListNode head;
public CircularLinkedList() {
head = null;
}
// 在链表中添加节点
public void append(int val) {
if (head == null) {
head = new ListNode(val);
head.next = head;
} else {
ListNode current = head;
// 找到最后一个节点(循环条件是找到指向头部的节点)
while (current.next != head) {
current = current.next;
}
ListNode newNode = new ListNode(val);
newNode.next = head;
current.next = newNode;
}
}
// 删除链表中的节点
public void delete(int val) {
if (head == null) return;
ListNode current = head;
ListNode prev = null;
do {
if (current.val == val) {
if (prev == null) {
// 删除的是头节点
head = head.next;
// 找到尾节点并更新其next指针
ListNode tail = head;
while (tail.next != current) {
tail = tail.next;
}
tail.next = head;
if (head == current) { // 链表只剩一个节点
head = null;
}
} else {
prev.next = current.next;
}
return;
}
prev = current;
current = current.next;
} while (current != head);
}
// 打印链表
public void printList() {
if (head == null) return;
ListNode current = head;
do {
System.out.print(current.val + " -> ");
current = current.next;
} while (current != head);
System.out.println("(head)");
}
}
使用循环链表
创建一个循环链表实例,并在链表中添加、删除节点并打印:
public class Main {
public static void main(String[] args) {
CircularLinkedList list = new CircularLinkedList();
// 向循环链表添加数据
list.append(1);
list.append(2);
list.append(3);
list.append(4);
// 打印循环链表
list.printList(); // 输出: 1 -> 2 -> 3 -> 4 -> (head)
// 删除循环链表中的一个节点
list.delete(3);
// 再次打印循环链表
list.printList(); // 输出: 1 -> 2 -> 4 -> (head)
}
}
在这个例子中,我们定义了一个循环链表的节点类ListNode
,它包含一个整数数据字段和一个指向下一个节点的指针(在循环链表中,这个指针最终会指回列表的头部)。CircularLinkedList
类管理循环链表,包括在链表中添加节点,删除具有特定值的节点,以及打印链表。
总结
循环链表比传统的单向链表或双向链表更适合于某些特定的应用场景,如需要周期性遍历的场合。它的实现略微复杂,因为需要特别注意更新头节点和尾节点的指针。掌握循环链表的实现和操作对于理解更复杂的数据结构和算法也是非常有帮助的。