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

链表中两种append算法实现的输出差异原因是什么?

链表append方法两种实现的差异原因

你的代码实现

首先是Node类:

class Node<T> {
  T value;
  Node<T>? nextNode;
  Node({required this.value, this.nextNode});

  @override
  String toString() {
    if (nextNode == null) return '$value';
    return '$value --> ${nextNode.toString()}';
  }
}

然后是LinkedList类,核心差异在append方法的两种变体:

class LinkedList<E> {
  Node<E>? head;
  Node<E>? tail;

  bool get isEmpty => head == null;
  // 在链表头部添加节点
  void push(E value) {
    if (isEmpty) {
      head = Node(value: value);
      tail = head;
      return;
    }
    head = Node(value: value, nextNode: head);
  }

  // 在链表尾部添加节点
  void append(E value) {
    if (isEmpty) {
      push(value);
      return;
    }
    tail!.nextNode = Node(value: value);
    tail = tail!.nextNode;  //* 变体1(正确)
    // tail = Node(value: value);  //** 变体2(错误)
  }

  @override
  String toString() {
    return head.toString();
  }
}

差异原因拆解

变体1的正确逻辑

当执行tail!.nextNode = Node(value: value);时,已经把新节点挂载到了原链表的末尾(当前tail节点的next指针指向这个新节点)。随后tail = tail!.nextNode;只是把LinkedList的tail变量更新为这个刚加入的节点,后续调用append时,依然能通过tail找到链表的真实末尾,继续挂载新节点,整个链表的链式结构是完整的。

变体2的错误逻辑

执行tail!.nextNode = Node(value: value);之后,你又执行了tail = Node(value: value);——这一步创建了一个全新的、和原链表无关的Node实例,完全断开了tail变量和原链表的联系:

  1. 第一次append(1):链表为空,调用push,head和tail都指向节点1。
  2. 第二次append(2):tail!.nextNode = Node(value:2)让节点1的next指向节点2(原链表现在是1→2),但紧接着tail = Node(value:2)让tail指向了一个新的孤立节点2,和原链表的节点2不是同一个对象。
  3. 第三次append(3):此时tail是那个孤立节点2,tail!.nextNode = Node(value:3)把节点3挂到了这个孤立节点的next上,但原链表的节点2的next还是null;然后tail = Node(value:3)又变成新的孤立节点3。
  4. 后续append(4)同理,所有新节点都只在tail自己的孤立链上,和head指向的原链表(1→2)完全脱节。

所以打印head时,只能遍历到原链表的1→2,后面的3、4根本不在这条链上,自然输出不出来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:18:13