Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Scala集合中没有不可变的双链表?_Scala_Collections_Linked List_Immutability - Fatal编程技术网

为什么Scala集合中没有不可变的双链表?

为什么Scala集合中没有不可变的双链表?,scala,collections,linked-list,immutability,Scala,Collections,Linked List,Immutability,看看问题,如果发问者对列表中某个元素的第一个和最后一个实例感兴趣,似乎更有效的解决方案是使用可以从列表末尾向后搜索的双链接列表。然而,CollectionsAPI中只有一个实现,而且它是可变的 为什么没有不可变的版本?因为每次要进行更改时都必须复制整个列表。使用普通链表,您至少可以在不复制所有内容的情况下预先添加到列表。如果你真的想在每次更改中复制所有内容,你不需要一个链接列表。您可以只使用不可变数组。作为对@KimStebel答案的补充,我想添加: 如果您正在搜索一个适合于促使您提出此问题的问

看看问题,如果发问者对
列表中某个元素的第一个和最后一个实例感兴趣,似乎更有效的解决方案是使用可以从列表末尾向后搜索的
双链接列表。然而,CollectionsAPI中只有一个实现,而且它是可变的


为什么没有不可变的版本?

因为每次要进行更改时都必须复制整个列表。使用普通链表,您至少可以在不复制所有内容的情况下预先添加到列表。如果你真的想在每次更改中复制所有内容,你不需要一个链接列表。您可以只使用不可变数组。

作为对@KimStebel答案的补充,我想添加:

如果您正在搜索一个适合于促使您提出此问题的问题的数据结构,那么您可以查看。

,因为从逻辑上讲,创建具有严格不变性的相互(循环)引用数据结构是不可能的

由于简单的存在排序优先级,您无法创建两个相互指向的节点,因为创建另一个节点时,其中至少一个节点将不存在


通过涉及懒惰的技巧(这是通过变异实现的)可以得到这种循环,但真正的问题是,为什么您首先想要这种东西?

这种结构有很多障碍,但有一个非常紧迫:双链接列表不能持久

这背后的逻辑非常简单:从列表中的任何节点,都可以到达任何其他节点。因此,如果我在这个列表DL中添加了一个元素X,并试图使用DL的一部分,我将面临这样的矛盾:从指向X的节点,一个可以到达部分(DL)中的每个元素,但是,根据双链表的属性,这意味着从部分(DL)的任何元素,我都可以到达指向X的节点。因为部分(DL)应该是不可变的,并且是DL的一部分,因为DL不包括指向X的节点,所以这是不可能的

非持久不变的数据结构可能有一些用途,但它们通常对大多数操作都不好,因为它们需要在生成派生时重新创建


现在,有一个小问题是创建相互引用的严格对象,但这是可以克服的。可以使用按名称参数和惰性VAL,也可以像Scala的列表一样:实际创建一个可变集合,然后在不可变状态下“冻结”它(请参见ListBuffer和它的toList方法)。

正如其他人所指出的,没有持久的双链接列表实现。你需要某种树来接近你想要的特征

特别是,您可能想看看,它提供了对前端和后端的O(1)访问、对前端和后端的摊销O(1)插入以及其他地方的O(logn)插入。(这与大多数其他常用的树不同,这些树到处都有O(logn)访问和插入。)

另见:

  • (由clojure.contrib中手指树的实现者提供)
  • (我没有亲自使用过,但它是谷歌最热门的产品)

在我的脑海中,我想不出任何方法可以避免双链表上的任何操作复制所有元素(而单链表可以共享尾部-例如O(1)
cons
)。总的来说,这听起来效率很低。仔细想想,我不知道有哪一个库具有不可变的双链表……在Haskell中,您正在寻找的数据结构将是(它比双线表稍微复杂一些,但在保持不可变性的同时有许多性能改进)。如果Scala没有一个等价的不变结构,我会感到惊讶;如果没有,那么让我们联系开发人员并提出要求。@Dan我相信Scala中的等价物会是。你关于“矛盾”的结论是错误的。您无法从列表的元素中访问任何内容,其中“元素”是您添加到列表中的对象。从列表对象向前和向后移动(对于持久列表,这些遍历操作将返回表示新位置的新列表对象)。一个简单的持久化实现是让列表将节点之间的前向和后向链接表示为两个(持久)哈希表,从一个节点到它的后续节点和前置节点,其中每个节点都包含一个元素。@Perildner所说的“元素”指的是指向该元素的节点。我在这方面做了正确的决定。记住,“持久”意味着不允许创建新列表,只允许创建新节点。不需要复制整个列表。请参阅我对下一个答案的评论。