【问题标题】:Efficient data structure for fast random access, search, insertion and deletion用于快速随机访问、搜索、插入和删除的高效数据结构
【发布时间】:2010-10-27 18:47:09
【问题描述】:

我正在寻找一种数据结构(或多个结构),它可以让我保留一个有序的整数列表,没有重复,索引和值在同一范围内。

我需要四个主要操作才能高效,按重要性粗略排序:

  1. 从给定索引中获取值
  2. 查找给定值的索引
  3. 在给定索引处插入值
  4. 删除给定索引处的值

使用一个数组,我在 O(1) 处有 1,但 2 是 O(N),插入和删除是昂贵的(我相信也是 O(N))。

链表有 O(1) 的插入和删除(一旦你有节点),但 1 和 2 是 O(N),因此抵消了收益。

我尝试保留两个数组 a[index]=value 和 b[value]=index,这会将 1 和 2 变成 O(1),但将 3 和 4 变成更昂贵的操作。

有没有更适合这个的数据结构?

【问题讨论】:

  • 应该不重要,但它是 C++
  • 这很重要;并非所有语言都提供相同的数据结构。例如,这个特定问题可以通过 C Judy 数组或 C# CPTrie 非常有效地解决。 (或者,当然,正如 Ayman 所建议的那样,某种平衡二叉树。)

标签: arrays data-structures list linked-list


【解决方案1】:

使用向量进行数组访问。

使用地图作为搜索索引,将下标插入向量。

  • 给定一个下标,从向量 O(1) 中获取值
  • 给定一个键,使用映射查找该值的下标。 O(lnN)
  • 插入一个值,推回向量 O(1) 摊销,插入下标 地图 O(lnN)
  • 删除一个值,从地图中删除 O(lnN)

【讨论】:

    【解决方案2】:

    如何用 RB-trees 实现 2?我们可以让他们在每次插入/删除操作时计算他们的孩子。这不会使这些操作持续时间显着延长。然后可以在 log n 时间内沿着树找到第 i 个元素。但是我在 java 和 stl 中都没有看到这个方法的实现。

    【讨论】:

      【解决方案3】:

      如何使用带二分查找的排序数组?

      插入和删除很慢。但考虑到数据是纯整数这一事实,如果您使用 C 或 C++,则可以通过调用 memcpy() 来优化。如果您知道数组的最大大小,您甚至可以避免在使用数组期间进行任何内存分配,因为您可以将其预先分配到最大大小。

      “最佳”方法取决于您需要存储多少项目,以及与查找相比,您需要插入/删除的频率。如果你很少插入或删除一个排序数组,使用 O(1) 访问值肯定会更好,但如果你经常插入和删除东西,二叉树可能比数组更好。在任何情况下,对于足够小的 n,数组最有可能击败树。

      如果考虑存储大小,那么数组也比树好。树还需要为它们存储的每个项目分配内存,并且内存分配的开销可能很大,因为您只存储较小的值(整数)。

      如果您从已排序的数组或带有内存(取消)分配的树中插入/删除,您可能想要分析更快的情况,即整数的复制。

      【讨论】:

      • 插入和删除在 OP 列表中排在最后,并且可以通过调用 memcpy() 来优化整数。
      • “有序”部分很重要,所以无法对数据进行排序。
      • @Leonel ordered 表示按照你指定的排序规则排序
      • 可能他的意思是“插入订单”
      【解决方案4】:

      我会使用red-black tree 将键映射到值。这为 1、3、4 提供了 O(log(n))。它还按排序顺序维护键。

      对于 2,我将使用哈希表将值映射到键,这将为您提供 O(1) 性能。当在红黑树中添加和删除键时,它还增加了 O(1) 开销来保持哈希表的更新。

      【讨论】:

      • 我知道我在某处读到过:cs.tau.ac.il/~wein/publications/pdfs/rb_tree.pdf
      • @Javier:红黑树绝对没有摊销的 O(1) 访问权限。当您读取树中的元素时,红黑树实际上并没有任何操作,因此没有摊销。没有二叉树,无论是否动态,都可以实现 o(n log n) 访问树中的 n 个任意元素。
      【解决方案5】:

      我非常喜欢平衡二叉树。它们有时比哈希表或其他结构慢,但它们更容易预测;对于所有操作,它们通常为O(log n)。我建议使用Red-black treeAVL tree

      【讨论】:

      • 哈希表不会保持数据有序。
      • 糟糕,我没有看到订购的部分......不过我已经修好了。
      【解决方案6】:

      如果您在 .NET 中工作,那么根据 MS 文档 http://msdn.microsoft.com/en-us/library/f7fta44c.aspx

      • SortedDictionary 和 SortedList 都有 O(log n) 用于检索
      • SortedDictionary 有 O(log n) 用于插入和删除操作,而 SortedList 有 O(n)。

      两者在内存使用和插入/删除速度方面有所不同。 SortedList 使用的内存比 SortedDictionary 少。如果从排序数据中一次性填充 SortedList,则它比 SortedDictionary 更快。因此,这取决于具体情况,哪种方式最适合您。

      此外,您对链接列表的论证并不是真正有效的,因为插入可能是 O(1),但您必须遍历列表才能找到插入点,所以实际上不是。

      【讨论】:

        【解决方案7】:

        我不知道您使用的是什么语言,但如果是 Java,您可以利用 LinkedHashMap 或类似的集合。它具有 List 和 Map 的所有优点,为大多数操作提供恒定的时间,并且具有大象的内存占用。 :)

        如果您不使用 Java,LinkedHashMap 的想法可能仍然适用于解决您的问题的可用数据结构。

        【讨论】:

        • 如何使用 LinkedHashMap 获取随机元素?
        【解决方案8】:

        树形图怎么样? log(n) 用于描述的操作。

        【讨论】:

          猜你喜欢
          • 2014-03-04
          • 2014-03-09
          • 1970-01-01
          • 2018-11-16
          • 1970-01-01
          • 1970-01-01
          • 2013-02-22
          • 1970-01-01
          • 2015-11-10
          相关资源
          最近更新 更多