1
38
跳过列表的特性使其有利于并发更新(即大多数加减是本地的),也使其不利于不变性(即列表中的许多早期项最终指向后面的项,并且必须进行更改)。 具体来说,跳过列表由如下结构组成:
现在,如果你有一个更新,比如说,删除
因此,树结构更适合于不变性(因为损坏总是局部受限的——只是您所关心的节点和它的直接父节点通过树的根向上)。
因此,写重数据结构可能更好地以可变方式实现(使用类似于跳过列表的方法,您只需要在本地锁定),而读重数据结构可能更好地以不变方式实现(其中树是更自然的数据结构)。 |
2
17
Andrew McKinlay的解决方案是真正的“真正的”函数式解决方案,但是它有一个缺点。您需要花费对数时间来访问一个元素,但是现在超出head元素的突变变得毫无希望。你想要的答案埋在无数的路径副本里! 我们能做得更好吗?
但是如果你仔细考虑一下搜索技巧专家的算法,你永远不会使用这个事实。 我们可以认为树中的每个节点都有一个首选链接,从左边到它的最上面的链接,在某种意义上可以认为是“拥有”该条目。
现在我们可以从一个简单的跳过列表开始
逐级扩展:
然后,你可以移动一个“手指”到位置8跟踪所有的指针,你必须翻转到那里。
这样看,我们可以看到跳过列表中的特权路径形成了一个生成树! 如果在树中只有特权指针并且使用这样的“瘦节点”,那么用手指移动一步就是一个O(1)操作。如果使用脂肪节点,那么手指向左/向右移动可能会更昂贵。 所有操作都保持O(logn),您可以像往常一样使用随机跳过列表结构或确定性跳过列表结构。
|
3
6
不是跳过列表,但似乎与问题描述相符:Clojure的持久红黑树(参见 PersistentTreeMap.java ). 来源包含以下通知:
这些树保持元素的顺序,并且在Rich Hickey使用这个词的意义上是“持久的”(不可变的,并且能够在构建更新版本时保持它们的性能保证)。
如果您想使用它们,可以使用函数在Clojure代码中构造实例
|
4
4
如果您只需要在跳过列表的前面添加cons,那么应该可以创建一个持久不变的版本。
|