【问题标题】:How to make a linked list from an array in Javascript如何从Javascript中的数组制作链表
【发布时间】:2018-03-25 01:52:49
【问题描述】:

这是基本代码

function ListNode(x) {
  this.value = x;
  this.next = null;
}

function linkedList(arr){
  let list = new ListNode(arr[0]);
  
  let selectedNode = list;
  for(let i = 1; i < arr.length; i++){
    selectedNode.next = new ListNode(arr[i]);
    selectedNode = selectedNode.next
  } 

  return list
}

l = [3, 1, 2, 3, 4, 5];

console.log(linkedList(l));

出于某种原因,它可以正常工作。我不明白 'list' 变量是如何在 linkedList(arr) 函数中更改/更新的。我看到 selectedNode = list,但 list 永远不会改变。 list 使用构造函数 new ListNode(arr[0]) 进行初始化,但在那之后,唯一改变的变量是 selectedNodelist.next 甚至没有代码可以更改为某些内容。

那么返回列表是如何返回完整链表的呢?

【问题讨论】:

  • 列表变量指向列表的头部。然后它设置 selectednode 也指向头部。通过设置选择节点旁边指向一个新节点,它正在更改列表指向的同一个顶部节点。这。 Selectnode 移动到新的下一个节点,并且它不断链接越来越多的节点。一直以来,列表仍然指向第一个节点。
  • selectedNode === list === new ListNode(arr[0])
  • 这就是LinkedList 的工作原理,从概念上讲。您只需要一个指向 head 节点的指针。 list 将新节点设置为节点的next 指针。所以最后你有一个链,你的head 指向另一个节点,head.next 指向另一个节点,这个节点再次指向带有 next 变量的某个节点,依此类推。您也可以在输出中清楚地看到这一点,它是一个嵌套结构

标签: javascript


【解决方案1】:

function linkedList(arr){
  return arr.reduceRight((next, value) => ({value, next}), null);
}

l = [3, 1, 2, 3, 4, 5];

console.log(linkedList(l));

对于这样一个简单的对象,您不需要 ListNode 类。

【讨论】:

  • 请给出解释...
【解决方案2】:

当您这样做时,let selectedNode = list; 两个变量指向内存中的相同值,在本例中为 listselectedNode。因此,修改链从列表和下游添加新的链接节点开始。

作者初始化了selectedNode,以list为链表的起点(根节点)。

这看起来像let selectedNode = list;的内存

  +-----------------+------------------+
  |       list      |  selectedNode    |
  +-----------------+------------------+
  |                 |         |        |
  |   {value: 3,    |         |        |
  |    next: null } <---------+        |
  |                 |                  |    
  +-----------------+------------------+

因此,每次迭代都会修改相同的list 对象,因为下一个节点与之前的节点绑定/链接:

selectedNode.next = new ListNode(arr[i]);  i = 1
+-------------------+------------------+
|       list        |  selectedNode    |
+-------------------+------------------+
|                   |            |     |
|   {               |            |     |
|     value: 3,     | Points to  |     |
|     next: {       | next       |     |
|        value: 1   <------------+     |
|        next: null |                  |
|      }            |                  |
|   }               |                  |
|                   |                  |    
+-------------------+------------------+

selectedNode.next = new ListNode(arr[i]);  i = 2
+-----------------------+------------------+
|       list            |  selectedNode    |
+-----------------------+------------------+
|                       |            |     |
|   {                   |            |     |
|     value: 3,         |            |     |
|     next: {           |            |     |
|        value: 1       | Points to  |     |
|        next: {        | next       |     |
|           value: 2,   <------------+     |
|           next: null  |                  |
|         }             |                  |
|     }                 |                  |
|   }                   |                  |
|                       |                  |    
+-----------------------+------------------+

等等。

【讨论】:

  • 我想我明白了。因此,通过将 new 添加到列表中,您可以使其成为构造函数,而不是包含值的变量。仍在试图弄清楚返回列表如何返回所有其他变量,但我会继续阅读,直到我理解为止
  • 它会返回整个内容,因为当您selectedNode = selectedNode.next 时,它在内存中也是一样的。在下一次迭代中,当您更改新的selectedNode 时,实际上是在更改旧的selectedNodenext 键,这实际上是在更改list
  • 大声感谢奥利弗。这太令人困惑了。我从未见过像这样的 javascript 共享变量。编辑:我可以阅读教程/类似的 SO 问题来详细说明这一点吗?
  • @TylerL 等一下,我想你会明白的。
  • @TylerL 看看更新的答案。如果你明白,请告诉我。
【解决方案3】:

当您将对象类型分配给变量时,变量的值不是实际对象,而是对它的引用。因此,当您执行selectedNode = list 时,两个变量都引用同一个对象,并且使用对该对象的任何引用对该对象所做的任何更改都将从其任何引用中可见。
简而言之:list 变量不会改变,但它引用的对象会改变。

【讨论】:

  • 所以在循环中,当 selectedNode.next 发生变化时,它实际上是在变化列表!如果有多个链表使用相同的构造函数呢?不可能?
  • @TylerL 哦,这绝对是可能的。如果通过构造函数你在谈论 linkedList(arr) {} 函数(它更像是一个工厂函数),每次调用它都会创建一个新的链表,因为 list 变量是函数的本地变量,并且每个函数调用都有它的自己的实例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-25
  • 2023-04-10
  • 2013-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多