You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java循环链表无限循环问题:List类修改方案咨询

解决循环链表打印/删除时的无限循环问题

嘿,我来帮你搞定这个循环链表的无限循环坑!先给你看修正后的Link和CircularList实现,再给你拆解问题根源和修改点:

public class Link {
    public int data;
    public Link next;

    public Link(int data) {
        this.data = data;
        this.next = null;
    }

    public void displayLink() {
        System.out.print("[" + data + "] ");
    }
}

2. CircularList 类代码

public class CircularList {
    private Link last; // 用尾节点维护循环链表,首尾操作更高效,也更容易避免指针混乱

    public CircularList() {
        last = null;
    }

    public boolean isEmpty() {
        return last == null;
    }

    // 尾部插入(保留你已实现的正确逻辑)
    public void insertLast(int data) {
        Link newLink = new Link(data);
        if (isEmpty()) {
            last = newLink;
            newLink.next = last; // 单个节点时自循环
        } else {
            newLink.next = last.next; // 新节点指向头节点
            last.next = newLink;      // 原尾节点指向新节点
            last = newLink;           // 更新尾节点
        }
    }

    // 打印链表:解决无限循环的核心!
    public void displayList() {
        if (isEmpty()) {
            System.out.println("链表为空");
            return;
        }
        Link current = last.next; // 从头节点开始遍历
        // 用do-while保证至少执行一次(哪怕只有一个节点),遍历到回到头节点就停止
        do {
            current.displayLink();
            current = current.next;
        } while (current != last.next);
        System.out.println();
    }

    // 删除头节点
    public Link deleteFirst() {
        if (isEmpty()) {
            return null;
        }
        Link first = last.next;
        if (first == last) { // 链表只有一个节点的情况
            last = null; // 清空链表,避免残留自循环节点
        } else {
            last.next = first.next; // 尾节点指向新的头节点,维持循环
        }
        return first;
    }

    // 删除指定数据的节点(处理所有边界情况)
    public Link delete(int key) {
        if (isEmpty()) {
            return null;
        }
        Link current = last.next;
        Link previous = last;

        // 遍历查找目标节点,直到回到头节点停止
        do {
            if (current.data == key) {
                // 分四种情况处理,保证循环不中断
                if (current == last && current == last.next) { // 唯一节点
                    last = null;
                } else if (current == last.next) { // 删除头节点
                    last.next = current.next;
                } else if (current == last) { // 删除尾节点
                    last = previous;
                    last.next = current.next;
                } else { // 删除中间节点
                    previous.next = current.next;
                }
                return current;
            }
            previous = current;
            current = current.next;
        } while (current != last.next);

        return null; // 没找到对应节点
    }
}

为啥你之前会无限循环?

你遇到的问题几乎是循环链表新手必踩的坑,主要是这两个原因:

  • 打印时没有正确的终止条件:循环链表没有null结尾,如果用普通的while(current != null)遍历,永远不会停下来——因为节点的next永远指向另一个节点,不会出现null。所以必须从首节点开始,遍历到回到首节点就停止,用do-while刚好适配这种场景(哪怕只有一个节点也能正确打印)。
  • 删除节点后没维护好循环指针:
    • 如果删除的是链表唯一的节点,没把last置为null,会残留一个自循环的节点,遍历的时候就会无限绕圈。
    • 删除头/尾节点时,没更新last或者last.next的指向,会导致循环断裂或者形成错误的循环链,遍历的时候就会停不下来。
  • 额外建议:用尾节点维护循环链表比头节点更合理,首尾插入/删除都能做到O(1)时间复杂度,也更容易避免指针混乱。

你可以把自己的代码和上面的对比,看看是不是在这些点上出了问题~

内容的提问来源于stack exchange,提问作者Devin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:25:40