我正在寻找在索引i处插入/删除日志(N)的“列表”。我把单词“List”放在引号中,因为我并不是说它是一个真正的Haskell List,而是任何带有一堆对象的有序容器(事实上,它可能需要内部的某种树)。我很惊讶我还没有找到一个很好的解决方案....
这是我迄今为止最好的解决方案 - 使用带有这两个函数的Data.Sequence。
doInsert position value seq = before >< ( value <| after)
where
(before, after) = splitAt position seq
doDelete position seq = before >< (drop 1 after)
where
(before, after) = splitAt position seq
虽然这些在技术上都是log(N)函数,但感觉就像我为每个插入/删除做了一堆额外的东西....换句话说,这就像K * log(N)的K一样缩放比它应该的大。另外,由于我必须自己定义这些内容,我觉得我正在使用Sequence来实现它不适合的东西。
有更好的方法吗?
这是一个相关的问题(虽然它只处理序列,我很乐意使用其他任何东西):Why doesn't Data.Sequence have `insert' or `insertBy', and how do I efficiently implement them?
是的,这个问题与我几天前发布的另一个问题有关:Massive number of XML edits
答案 0 :(得分:2)
有一些结构,如catenable seqs,catenable queues等,可以给你O(1)加入。然而,我所知道的所有这些结构都通过给你O(i)分裂而逃脱了。如果你想分割和加入两者尽可能最佳,我认为一个fingertree(aka Sequence
)是你最好的选择。 Sequence
的结构方式的全部要点是确保分裂,连接等在分裂和连接时有一个渐近但不太可怕的杂耍,等等。
如果你可以逃脱IntMap
开始稀疏并变得更密集,并且偶尔会重建&#34;当事情变得过于密集时,可能会给你更好的表现 - 但这实际上取决于你的使用模式。
答案 1 :(得分:0)
如果您仔细使用预定义的Haskell列表,那么它们应该没有问题。 (例如,在连接两个列表时)。
如果您希望找到列表的实现,并且有效插入和删除,AVLTree或任何类型或平衡的二叉树都可以工作。 例如,在AVLTree中存储一个元组(Int,a),其中Int是列表的索引和elem。 因此,就平均复杂性而言,操作将是对数的插入和删除。
我希望这能回答你的问题。