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

问题描述 投票:0回答:2

考虑一个模仿 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 等等?

javascript class oop linked-list this
2个回答
3
投票

当构造函数运行时,

this.tail
this.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
时,
second
对象的 next 属性将被更新,所以我们得到:

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

是的,这个变化也是可以从

this.head
追溯到的,因为……它是一个链表……所以它应该是可追溯的。由于每个
next
属性都引用下一个节点,因此您可以找到从
head
到任何节点的路径。


0
投票

哇上面的答案比水还清楚

© www.soinside.com 2019 - 2024. All rights reserved.