【问题标题】:Fastest data structure for inserting/sorting用于插入/排序的最快数据结构
【发布时间】:2011-04-07 19:29:20
【问题描述】:

我需要一个可以插入元素并尽可能快地自行排序的数据结构。我将插入比排序更多的内容。删除不是什么大问题,空间也更大。我的具体实现会将节点另外存储在一个数组中,因此查找将是 O(1),即您不必担心。

【问题讨论】:

  • 如果通过数组查找,为什么需要对数据结构进行排序?每次插入后是否需要按顺序排列?
  • 是的,插入后需要按顺序。我不会直接索引元素,而是节点,它应该可以访问它的相邻节点。
  • 你自相矛盾。问题是“我将插入比排序更多的内容”,但您的评论说“它需要在 [每个] 插入之后按顺序排列”。如果前者是真的,那么我的回答可能是合适的。如果后者是真的,那么你可能最好用一棵树,正如小队所建议的那样(尽管我不确定它是否需要平衡,正如他所建议的那样,因为查找不是什么大问题)。
  • 糟糕,没有正确思考。我的意思是它不必在每次插入后都必须按顺序排列。对不起。

标签: sorting data-structures insert performance


【解决方案1】:

只需使用self-balanced binary search trees 之一,如红黑树。

【讨论】:

  • 我想知道是否有更快的方法,另外我想手动平衡/排序。
  • 如果您希望在每次插入后对其进行排序,并使用任意数量的元素,这样您就不能只为每个项目提供存储桶,那么树就是要走的路。在相同的操作中插入和排序;恐怕你的速度不会比这快多少。
【解决方案2】:

如果您插入的 很多 多于排序,那么最好使用未排序的列表/向量,并在需要对其进行排序时对其进行快速排序。这使插入速度非常快。一个1 的缺点是排序是一个相对冗长的操作,因为它没有分摊到许多插入。如果您依赖相对恒定的时间,这可能会很糟糕。

1 想想看,还有第二个缺点。如果你低估了你的排序频率,这可能很快最终会比树或排序列表慢。例如,如果您在每次插入后进行排序,那么插入+快速排序循环将是一个坏主意。

【讨论】:

  • @"虽然我不确定它是否需要平衡,正如他所建议的那样,因为查找不是什么大问题" 如果它是平衡的,插入会不会更快?附: “查找”并不是指搜索。
  • @someguy:嗯,我想这取决于实际发生了多少平衡开销,以及它阻止了多少遍历。
  • 你可以很聪明地进行排序。如果为列表/向量创建包装器,则可以跟踪已排序的部分(它位于列表的前面,因此您只需要一个索引)。然后,当您想求助时,只需对未排序的部分进行排序并合并即可。那么复杂度远低于正常的O(n log n)排序。
【解决方案3】:

使用任何平衡二叉树,例如 AVL 树。它应该为您正在寻找的两个操作提供 O(lg N) 时间复杂度。

【讨论】:

    【解决方案4】:

    如果您不需要随机访问数组,您可以使用Heap

    最差和平均时间复杂度:

    • O(log N) 插入
    • O(1) 读取最大值
    • O(log N) 去除最大值

    可以重新配置以给出最小值而不是最大值。通过重复删除最大/最小值,您可以得到一个 O(N log N) 的排序列表。

    【讨论】:

      【解决方案5】:

      如果您可以在每次排序之前进行大量插入,那么显然您应该只追加项目并在需要时立即进行排序。我最喜欢的是归并排序。即 O(N*Log(N)),行为良好,存储操作最少(new、malloc、树平衡等)

      但是,如果集合中的值是整数并且相当密集,则可以使用 O(N) 排序,您只需将每个值用作足够大数组的索引,并在该处设置布尔值 TRUE指数。然后您只需扫描整个数组并收集为 TRUE 的索引。

      您说您将项目存储在查找为 O(1) 的数组中。除非您使用的是哈希表,否则这表明您的项目可能是密集整数,所以我不确定您是否有问题。

      无论如何,内存分配/删除是昂贵的,如果可以的话,你应该通过预分配或池化来避免它。

      【讨论】:

        【解决方案6】:

        我在使用Skip List 完成此类任务方面有一些很好的经验

        至少在我的情况下,与首先将所有内容添加到列表然后在最后对其进行排序相比,它快了大约 5 倍。

        【讨论】: