为什么this.tail会更改我的Linkedlist类中this.head的属性



考虑一个LinkedList类,它模仿LinkedList数据结构,如下所示:

class LinkedList {
constructor(value) {
this.head = {
value: value,
next: null
};
this.tail = this.head;
this.length = 1;
}
append(value) {
const newNode = {
value: value,
next: null
}
this.tail.next = newNode; // why does this change head.next ?
this.tail = newNode;
this.length++;
return this;
}
}
let myLinkedList = new LinkedList(10);
myLinkedList.append(5);

日志输出

LinkedList {
head: { value: 10, next: { value: 5, next: null } },
tail: { value: 5, next: null },
length: 2
}

我看到this.tail.next也会更改tail的下一个属性(然后this.tail = newNode会将tail重新分配给newNode(。我不明白的是,为什么this.tail.next也会更改this.head的下一个属性?

此外,当将另一个数字附加到列表myLinkedList.append(16)时,它会不断更新head的下一个属性,如下所示:

LinkedList {
head: { value: 10, next: { value: 5, next: [Object] } },
tail: { value: 16, next: null },
length: 3
}

也许一个可能的原因与我定义this.tail = this.head的构造函数有关?但我真的不确定,因为这个只分配头到尾的值。

综上所述,我的问题是为什么this.tail.next = newNode会改变头部的下一个属性?此外,当附加另一个值时,为什么要更改head.next.next等等?

当构造函数运行时,this.tailthis.head引用同一个对象,因此您对this.tail.next的任何赋值都可以在this.head中看到,因为这实际上是对正在变异的同一对象的引用。

将其可视化可能会有所帮助。一旦构造函数运行,我们就会出现这种情况:

this.head
↓          
┌───────────┐
│ value: 10 │
│ next: null│
└───────────┘
↑
this.tail

然后append(5)将首先创建一个新节点:

this.head        newNode
↓                ↓
┌───────────┐    ┌───────────┐
│ value: 10 │    │ value: 5  │
│ next:null │    │ next:null │
└───────────┘    └───────────┘
↑
this.tail

然后执行this.tail.next = newNode;,这是对第一个对象中next属性的修改

this.head        newNode
↓                ↓
┌───────────┐    ┌───────────┐
│ value: 10 │    │ value: 5  │
│ next: ———————→ │ next:null │
└───────────┘    └───────────┘
↑
this.tail

事实上,这也改变了this.head.next。。。因为它是完全相同的属性。

然后执行this.tail = newNode;

this.head        newNode
↓                ↓
┌───────────┐    ┌───────────┐
│ value: 10 │    │ value: 5  │
│ next: ———————→ │ next:null │
└───────────┘    └───────────┘
↑
this.tail

下一次调用append时,第二个对象的next属性将被更新,因此我们得到:

this.head                         newNode
↓                                 ↓
┌───────────┐    ┌───────────┐    ┌───────────┐
│ value: 10 │    │ value: 5  │    │ value: 16 │
│ next: ———————→ │ next: ———————→ │ next:null │
└───────────┘    └───────────┘    └───────────┘
↑
this.tail

是的,这种变化也可以追溯到this.head,因为。。。它是一个链接列表。。。因此它应该是可追踪的。由于每个next属性都指向下一个节点,因此可以找到从head到任何节点的路径。

最新更新