Haskell:使用O(1)追加和O(1)索引的Datastruture?

时间:2012-05-03 21:51:41

标签: haskell data-structures vector

我在Haskell中寻找支持快速索引和快速追加的数据结构。这是一个由递归引起的记忆问题。

从矢量在c ++中工作的方式(这是可变的,但在这种情况下应该无关紧要)似乎可以使用(摊销的)O(1)追加和O(1)索引的不可变向量(ok) ,它不是,看到这个问题的评论)。这在Haskell中是不可能的,还是我应该使用DataAsecece(无论如何)A(1)追加和O(log(min(i,n-i)))索引?

在相关的说明中,作为Haskell新手,我发现自己渴望得到一个实用,简洁的Haskell数据结构指南。理想情况下,这将对最实用的数据结构以及性能特征和指向Haskell库的指针进行相当全面的概述。似乎有很多信息,但我发现它有点分散。我问的太多了吗?

3 个答案:

答案 0 :(得分:9)

如果内存服务,则C ++向量实现为具有边界和大小信息的数组。当插入会增加超出大小的边界时,大小会加倍。这是O(1)时间插入的摊销(不是你声称的O(1)),并且可以使用Array类型在Haskell中模拟得很好,可能是合适的IO或{{1} } prepended。

答案 1 :(得分:9)

对于简单的memoization问题,您通常希望构建一次表,然后不再修改它。在这种情况下,您可以避免担心附加,而是将memoization表的构造视为一个操作。

一种方法是利用延迟评估,并在我们构建它时参考表格。

import Data.Array
fibs = listArray (0, n-1) $ 0 : 1 : [fibs!(i-1) + fibs!(i-2) | i <- [2..n-1]]
  where n = 100

当表的元素之间的依赖关系很难提出一个提前评估它们的简单顺序时,此方法特别有用。但是,它需要使用盒装数组或向量,由于额外的开销,这可能使这种方法不适合大型表。

对于未装箱的向量,您可以使用constructN之类的操作,它允许您以纯粹的方式构建表,同时使用下方的突变使其高效。它通过给你传递一个到目前为止构造的向量前缀的不可变视图的函数来做到这一点,然后你可以用它来计算下一个元素。

import Data.Vector.Unboxed as V
fibs = constructN 100 f
  where f xs | i < 2 = i
             | otherwise = xs!(i-1) + xs!(i-2)
             where i = V.length xs

答案 2 :(得分:6)

请查看this,以便更明智地选择应该使用的内容。

但简单的说法是,如果你想要相当于C ++向量,请使用Data.Vector