我试图了解push()
方法如何在JS中使用tails。这是代码:
class Node {
constructor(val) {
this.val = val;
this.next = null;
}
}
class SinglyLinkedList {
constructor() {
this.length = 0;
this.head = null;
this.tail = null;
}
push(val) {
const newNode = new Node(val)
if (this.head===null) { // happens only once
this.head = newNode;
this.tail = this.head;
} else {
this.tail.next = newNode; // this.a.next = b node???
this.tail = newNode;
}
this.length++
}
具体来说,我不理解push()
方法中的else
部分。如果我们说this.tail.next = newNode
,那么head
的每个next
是如何被分配一个新节点的?头和尾之间的关系在哪里?通过说this.tail.next = newNode
,我们如何访问列表的head
属性?当我运行这个代码时,它运行得非常正确,这让我很困惑
const myList = new SinglyLinkedList();
myList.push("111");
myList.push("222");
myList.push("333");
console.log(myList);
输出:
SinglyLinkedList {
length: 3,
head: Node { val: '111', next: Node { val: '222', next: [Node] } },
tail: Node { val: '333', next: null } }
如果我们说this.tail.next=newNode,
head
的每个next
如何被分配一个新节点?head和tail之间的关系在哪里?通过this.tail.next=newNode,我们如何访问列表的head属性?
让我们回到空列表。第一次添加节点时,我们进入if
块,其中head
和tail
都将引用相同的新节点。这意味着,从那一刻起,无论你在tail
中突变了什么,都会突变head
,因为它们指的是同一个对象。
现在执行第二个push
,并且我们进入else
块。在那里,我们将新节点分配给tail
的next
属性。但由于这是head
所指的同一对象,我们实际上在这里设置了head.next
!这只发生在第二个push
上,因为在该分配之后,tail
被分配了一个新的引用(next
(,因此从那时起,head
和tail
指代不同的节点。
图示:
push('111')
:之后
head
↓
111
↑
tail
push('222')
时,this.tail.next = newNode;
后:
head
↓
111 → 222
↑
tail
并且在CCD_ 30之后在同一推送期间:
head
↓
111 → 222
↑
tail
当push('333')
时,在this.tail.next = newNode;
之后:
head
↓
111 → 222 → 333
↑
tail
并且在CCD_ 33之后在同一推送期间:
head
↓
111 → 222 → 333
↑
tail
好的,我试着解释一下为什么会这样。
- 第一次推送时,
head
和tail
都指向同一个节点 - 然后,当您第二次推送时,
this.tail.next = newNode
将新节点添加到head
和tail
的下一个属性中 - 然后
this.tail = newNode
更新tail
的节点,使head
的下一个节点与尾部相同
如果要检查上面的步骤2,请注释掉this.tail = newNode
并推两次。您将看到head
和tail
的下一个属性是相同的。