链表中两种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变量和原链表的联系:
- 第一次append(1):链表为空,调用push,
head和tail都指向节点1。 - 第二次append(2):
tail!.nextNode = Node(value:2)让节点1的next指向节点2(原链表现在是1→2),但紧接着tail = Node(value:2)让tail指向了一个新的孤立节点2,和原链表的节点2不是同一个对象。 - 第三次append(3):此时
tail是那个孤立节点2,tail!.nextNode = Node(value:3)把节点3挂到了这个孤立节点的next上,但原链表的节点2的next还是null;然后tail = Node(value:3)又变成新的孤立节点3。 - 后续append(4)同理,所有新节点都只在
tail自己的孤立链上,和head指向的原链表(1→2)完全脱节。
所以打印head时,只能遍历到原链表的1→2,后面的3、4根本不在这条链上,自然输出不出来。
内容的提问来源于stack exchange,提问作者zex_rectooor
相关产品推荐
相关产品推荐

