【问题标题】:"List" with efficient insert/delete具有高效插入/删除的“列表”
【发布时间】:2014-01-06 01:30:24
【问题描述】:

我正在寻找一个在索引 i 处带有 log(N) 插入/删除的“列表”。我把“列表”这个词放在引号中,因为我并不是说它是一个实际的 Haskell 列表,而是任何带有一堆对象的有序容器(实际上,它内部可能需要某种树)。我很惊讶我还没有找到一个很好的解决方案....

这是迄今为止我最好的解决方案——将 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

【问题讨论】:

  • 为什么不:: Data.Map.Map Int a
  • 我不确定我是否理解对Data.Sequence 的反对意见。你能详细说明你的成功标准是什么吗?替代选择需要证明比 Data.Sequence 有明显改进?
  • @DanielWagner-Data.Sequence 是可以接受的,但它有我上面提到的问题(应该有一种插入/删除的方法,而无需中间人撕开并重建整个树,事实上这些函数不是库的一部分已经让我觉得它不是为了这个目的而编写的)。我只是想找到 Haskell 惯用的解决方案,或者验证这确实是推荐的方式。我的意思是,真的,为什么插入/删除不是序列库的一部分,我错过了什么?
  • 您可能想尝试使用列表的简单实现,然后对瓶颈进行基准测试和优化。使用 Functor、Foldable 和 Traversable 等类型类可以更轻松地交换数据结构。
  • 我认为 Data.Sequence 可以达到目的。两种操作(拆分和追加 (>

标签: haskell


【解决方案1】:

有一些结构,如可连接序列、可连接队列等,可以为您提供 O(1) 连接。但是,我所知道的所有此类结构都通过给你 O(i) 拆分来解决这个问题。如果您希望拆分和连接两者尽可能最佳,我认为手指树(又名Sequence)是您最好的选择。 Sequence 的结构方式的全部意义在于确保拆分、合并等在拆分和合并时有一个渐近不可怕的杂耍量。

如果您可以摆脱IntMap,它开始稀疏并变得更密集,并且当事情变得太密集时偶尔“重建”,那么可能你有更好的表现——但这真的取决于你的使用模式。

【讨论】:

    【解决方案2】:

    如果您仔细使用预定义的 Haskell 列表,它们应该没有问题。 (例如连接两个列表时)。

    如果您想找到一个列表实现,具有高效的插入和删除,AVLTree 或任何种类或平衡的二叉树都可以工作。 例如,在 AVLTree 中存储一个元组 (Int, a),其中 Int 是列表的索引,一个元素。 因此,平均而言,插入和删除操作将是对数的。

    我希望这能回答你的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-22
      • 1970-01-01
      • 2023-03-31
      • 2015-01-02
      • 2020-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多