为什么在Finger Trees和Linked Lists等中使用元组

时间:2012-07-01 21:01:28

标签: c# data-structures tree functional-programming

关于手指树,如this paper中所见,并由Eric Lippert在this post中提到。

我不明白为什么使用显式元组排列,而不是每个手指的某种链表结构。也就是说,为什么我们定义One(x), Two(x, y), Three(x, y, z), Four(x, y, z, a)并且不仅仅有一个不太理想的deque对象而且LessOptimalDeque.AddLeft(x)

它有点慢吗?我的意思是,即使你可以使用一些数据结构来重用一些节点/节点组的内存吗?

在论文中,甚至提到:

  

练习1.在上面的演示中,为简单起见,我们将数字表示为列表。   更准确和有效的实现将使用类型

data Digit a = One a  
| Two a a
| Three a a a
| Four a a a a
  

重复上述定义,使用这种数字定义。

我不知道为什么它更有效率。它只是与作者使用的函数语言相关的东西,也可以使用我上面提出的数据结构来完成吗?

修改
enter image description here

如此实施手指呢?

1 个答案:

答案 0 :(得分:2)

要了解为什么这在Haskell中更有效:

data Digit a
           = One a  
           | Two a a
           | Three a a a
           | Four a a a a

比这(矢量的明显编码):

data List a = One a
            | Many a (List a) -- a linked list of at least one element.

我们可以观察分配DigitList所需的堆结构。

Four 'x' 'y' 'z' 'd'

vs

Many 'x' (Many 'y' (Many 'z' (One 'd')))

在前一种情况下,我们保存了3个构造函数。在后者中,我们被迫为结构的(可能是无限的)尾部分配额外的堆对象。通常,Digit表示将分配 O(n-1)更少的堆单元格,因为结构的大小在最外层的构造函数中编码。我们还可以确定 O(1)中的大小。