Java 循环链表的实现

循环链表是一种特殊的链表结构,它的尾节点指向头节点,形成一个环。这使得从链表的任何一个节点出发都能遍历到链表中的所有节点。在实际应用中,循环链表常用于构建环形队列、游戏中的玩家回合等场景。

1. 循环链表的结构设计

在 Java 中实现循环链表,我们需要定义一个节点类(Node)和一个循环链表类(CircularLinkedList)。节点类包含数据和指向下一个节点的引用,而循环链表类则包含对头节点的引用及与链表相关的各种操作方法。

1.1 节点类

节点类的设计如下:

public class Node {
    int data;       // 节点数据
    Node next;     // 指向下一个节点的引用

    public Node(int data) {
        this.data = data;
        this.next = null;  // 初始化时,设置下一个节点为 null
    }
}

1.2 循环链表类

循环链表类的主要功能包括插入节点、删除节点、遍历链表等。

public class CircularLinkedList {
    private Node head;  // 指向链表头部的引用

    // 构造函数
    public CircularLinkedList() {
        this.head = null;
    }

    // 插入节点到链表末尾
    public void insert(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            newNode.next = head;  // 指向自身,形成循环
        } else {
            Node temp = head;
            while (temp.next != head) { // 遍历到最后一个节点
                temp = temp.next;
            }
            temp.next = newNode;  // 将最后节点的 next 指向新节点
            newNode.next = head;   // 新节点的 next 指向头节点
        }
    }

    // 遍历链表
    public void traverse() {
        if (head == null) return;
        Node temp = head;
        do {
            System.out.print(temp.data + " ");
            temp = temp.next;
        } while (temp != head);
        System.out.println();
    }

    // 删除指定节点
    public void delete(int key) {
        if (head == null) return;

        Node current = head;
        Node previous = null;

        // 如果删除的是头节点
        if (current.data == key) {
            // 处理链表只有一个节点的情况
            if (current.next == head) {
                head = null; // 链表为空
                return;
            } else {
                // 找到最后一个节点以更新指针
                while (current.next != head) {
                    current = current.next;
                }
                current.next = head.next; // 更新最后节点的 next
                head = head.next; // 更新头节点
            }
            return;
        }

        // 遍历链表找到要删除的节点
        do {
            previous = current;
            current = current.next;
        } while (current != head && current.data != key);

        if (current.data == key) {
            previous.next = current.next;  // 跳过要删除的节点
        }
    }
}

1.3 类图

以下是循环链表的类图表示:

classDiagram
    class Node {
        +int data
        +Node next
        +Node(int data)
    }

    class CircularLinkedList {
        -Node head
        +CircularLinkedList()
        +void insert(int data)
        +void traverse()
        +void delete(int key)
    }

    Node --> CircularLinkedList : contains

2. 功能测试

接下来,我们可以创建一个简单的测试程序来验证我们的循环链表实现。

public class Main {
    public static void main(String[] args) {
        CircularLinkedList cll = new CircularLinkedList();
        cll.insert(1);
        cll.insert(2);
        cll.insert(3);
        
        System.out.print("链表内容: ");
        cll.traverse();  // 输出: 1 2 3

        cll.delete(2);
        System.out.print("删除 2 后的链表内容: ");
        cll.traverse();  // 输出: 1 3

        cll.delete(1);
        System.out.print("删除 1 后的链表内容: ");
        cll.traverse();  // 输出: 3
    }
}

3. 开发过程甘特图

在开发循环链表的过程中,我们可以使用甘特图来描述各个阶段的时间安排如下:

gantt
    title 循环链表开发过程
    dateFormat  YYYY-MM-DD
    section 设计
    理解问题          :done,  des1, 2023-10-01, 1d
    设计类结构        :done,  des2, after des1, 1d
    section 实现
    编写节点类       :done,  imp1, after des2, 1d
    编写循环链表类   :done,  imp2, after imp1, 2d
    section 测试
    编写测试代码     :done,  test1, after imp2, 1d
    运行测试         :done,  test2, after test1, 1d

4. 总结

通过以上实现,我们成功地构建了一个基本的循环链表,并实现了一系列常用的方法。循环链表的特点是节点之间形成环状结构,能够有效地支持插入、删除和遍历操作。这种数据结构在实际编程中非常有用,特别是在需要处理重复循环的场景中。希望通过这个示例,你能够深入理解循环链表的工作原理及其应用。