数据结构-循环链表实践教程

循环链表是一种链表,其中最后一个节点指向第一个节点,形成一个环。循环链表可以是单向的也可以是双向的。在循环链表中,不存在任何节点的下一个节点为空,这使得从列表的任何点开始都可以轻松地遍历整个链表。由于循环链表的特性,它常用于需要周期重复访问列表的场景,例如轮转调度算法。

实现单向循环链表

首先,定义链表的节点类。和单向链表类似,循环链表的节点包含数据域和指向下一个节点的指针。

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类管理循环链表,包括在链表中添加节点,删除具有特定值的节点,以及打印链表。

总结

循环链表比传统的单向链表或双向链表更适合于某些特定的应用场景,如需要周期性遍历的场合。它的实现略微复杂,因为需要特别注意更新头节点和尾节点的指针。掌握循环链表的实现和操作对于理解更复杂的数据结构和算法也是非常有帮助的。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值