关于单链表push方法实现的疑惑:tail.next修改为何影响head.next?
单链表push方法的指针问题解析
异常代码实现
class Node { constructor(val) { this.val = val; this.next = null; } } class SinglyLinkedList { constructor() { this.head = null; this.tail = null; this.length = 0; } push(val) { let newNode = new Node(val); if (!this.head) { this.head = newNode; this.tail = newNode; } else { this.tail.next = newNode; } this.length++; return this; } } let list = new SinglyLinkedList() list.push(1) list.push(2)
异常执行结果
{ "head": { "val": 1, "next": { "val": 2, "next": null } }, "tail": { "val": 1, "next": { "val": 2, "next": null } }, "length": 2 }
核心疑问
- 执行
list.push(2)时,else分支仅执行this.tail.next = newNode;,为何head.next也被赋值? - 修正代码在else分支新增
this.tail = newNode;后,修改tail时head却没有变化,这是为什么?
修正后的代码
push(val) { let newNode = new Node(val); if (!this.head) { this.head = newNode; this.tail = newNode; } else { this.tail.next = newNode; this.tail = newNode; } this.length++; return this; }
修正后执行结果
{ "head": { "val": 1, "next": { "val": 2, "next": null } }, "tail": { "val": 2, "next": null }, "length": 2 }
问题解答
这本质是JavaScript引用类型的特性:
- 第一次执行
push(1)时,this.head和this.tail都指向同一个Node实例(值为1的节点)。此时head和tail只是两个指针变量,它们指向的是内存中的同一个对象。 - 执行
push(2)进入else分支时,this.tail.next = newNode是在修改这个共享节点的next属性。因为head也指向该节点,所以head.next自然会同步看到这个变化——你修改的是指针指向的对象本身,不是指针变量。 - 修正代码中新增的
this.tail = newNode,是直接修改tail这个指针变量的指向,让它指向新创建的节点(值为2的节点)。这时候head指针的指向没有被改变,它依然指向原来的节点(值为1的节点),所以head不会跟着变化。
简单区分:
- 修改
tail.next是修改指针指向的对象的属性,所有指向该对象的指针都会看到变化; - 修改
tail是修改指针变量本身的指向,不会影响其他指针的指向。
内容的提问来源于stack exchange,提问作者jhchoi
相关产品推荐
相关产品推荐

