序列比在haskell中搜索的矢量更快吗?

时间:2018-06-18 12:40:06

标签: haskell

除了列表之外,我在haskell中使用数据结构。我的目标是在Data.VectorData.SequenceData.List等中选择一个容器...我的问题如下:

我必须创建一个序列(从数学上讲)。序列从0开始。在每次迭代中,生成两个新元素,但是根据第一个元素是否已经在序列中,只应附加一个元素。因此,在每次迭代中都会调用elem函数(请参阅下面的伪代码)。

appendNewItem :: [Integer] -> [Integer]
appendNewItem acc = let firstElem  = someFunc
                        secondElem = someOtherFunc
                        newElem    = if firstElem `elem` acc 
                                        then secondElem
                                        else firstElem
                    in  acc `append` newElem

sequenceUptoN :: Int -> [Integer]
sequenceUptoN n = (iterate appendNewItem [0]) !! n

appenditerate函数取决于您使用的集合(我在类型签名中使用列表以简化)。

问题是:我应该使用哪种数据结构?由于手指树的内部结构,此任务的Data.Sequence更快吗?

非常感谢!!

2 个答案:

答案 0 :(得分:6)

不,序列搜索速度不快。 Vector只是一块平坦的内存,通常可以提供最佳的查找性能。如果要优化搜索,请使用Data.Vector.Unboxed。 (普通的“盒装”变体也很不错,但它实际上只包含引用到平坦内存块中的元素,所以它的查找速度并不快。)

但是,由于内存布局平坦,Vector 不适合(纯功能)追加:基本上,无论何时添加新元素,整个数组都必须是复制,以免使旧的无效(其他人可能仍在使用)。如果你需要追加,Seq是一个不错的选择,虽然它没有破坏性追加的速度快:为了获得最大的性能,你需要预先分配一个未初始化的{{3}使用ST monad填充所需大小,并冻结结果。但这比纯功能替代方案更加繁琐,因此除非你需要挤出所有性能,否则Data.Sequence是可行的方法。如果想要追加,而不是查找元素,那么反向顺序的普通旧列表也可以做到。

答案 1 :(得分:4)

我建议将Data.SequenceData.Set结合使用。 Sequence用于保存值序列,Set用于跟踪集合。

SequenceListVector都是处理值的结构,其中结构中的位置在编制索引时具有最重要的意义。在列表中,我们可以有效地操纵前面的元素,在序列中我们可以根据最近端的距离对数来操纵元素,在矢量中我们可以在恒定时间内访问任何元素。但是,如果长度不断变化,那么矢量就不那么有用了,所以在这里排除它们的使用。

但是,您还需要在列表中查找某个值,这些结构对此没有帮助。您必须搜索整个列表/序列/向量以确定不存在新值。 Data.MapData.Set是您根据Ord定义索引值的两种结构,并允许您在log(n)中查找/插入。因此,以内存使用为代价,您可以在firstElem时间内查看集合中log(n)的存在,然后在常量时间内将newElem添加到序列的末尾。只需确保在添加或获取新元素时保持这两个结构同步。