连续(未固定)随机数输入的最佳排序算法是什么?

时间:2016-06-23 08:26:27

标签: algorithm sorting data-structures binary-tree binary-search-tree

假设我有一个系统一个接一个地接收连续随机数作为输入(0,5,2,10,6,20......)

我的目的是以最佳表现对它们进行排序。

因此,每次迭代后输出大小都会增加,并且输入是连续的。

我想使用插入排序或BST,但我不确定这个问题有什么用处,因为我知道插入排序为O(n-n^2),BST插入为O(log(n))

请提出任何建议?

6 个答案:

答案 0 :(得分:3)

我认为使用承诺O(log n)性能的一些BST(如AVL,黑红等)是您的最佳选择。

使用树的有序遍历完成打印当前数据。

答案 1 :(得分:3)

如果需要在每次添加元素时进行排序,这不是排序问题,而是插入问题。任何排序算法都是过度的。

如果您的数据必须存储在数组中,则无法对元素进行移位,解决方案为Ω(N)。这通过直接插入(O(N))有效地实现。 (二分法搜索然后插入将进行较少的比较,但不确定您是否会注意到差异。)

如果你有更多的自由,BST确实是一种更有效的解决方案。如果您需要绝对保证最坏情况下的成本(O(Log N)),BST需要平衡(所以AVL,Red-Black ......符合您的口味)。如果您的数据足够随机,则可能没有必要。

如果您的数据具有特殊属性(例如小离散范围),则ad-hoc解决方案可以执行此操作。在给定的示例中,简单的计数直方图将实现O(1)更新时间。

答案 2 :(得分:1)

插入排序对于小输入(小于1000)是有效的,否则因为它需要O(n ^ 2)的运行时间,如果你不确定你的输入增长到什么程度,它的复杂性会非常快。然后使用运行时间为O(nlogn)的快速排序或堆排序,它比O(n ^ 2)快得多。

答案 3 :(得分:1)

有几个因素会影响解决方案的效率:

  • 查找插入点的READS数
  • 插入的数量(例如轮班,重新平衡)
  • 总内存/位置(影响缓存未命中)常量(K)的大小是相关的,因为它会影响每个缓存级别中适合的元素数量。
  • 分支预测未命中

请注意,根据数据结构,这些数据的变化会比算法更多,因为随着每个元素的添加,算法似乎始终是插入排序的变体

Data Structure | READS  | WRITES | Memory     | locality | Branches
---------------|--------|--------|------------|----------|---------
Sorted Vector  |O(logN) | O(N)   | O(N)       | high     | high (FFTFFT)
Linked List    |O(N)    | O(1)   | O(K*N)     | low      | low  (FFFFFFFFFFT)
Red Black Tree |O(logN) | O(K)   | O(K*NlogN) | low      | high (FFTFFT)
Btree 16 node  |O(logN) | O(16)  | O(NlogN)   | medium   | medium (FFTF)

* K表示比具有相同O()的其他解决方案明显更高的常数

最佳解决方案可能会根据当前的架构限制而有所不同。如果内存/高速缓存大小很小,则排序的向量可能是最佳的。 如果分支未命中是昂贵的,链接列表可能是最佳的,因为分支除了最后一个都将是假的

但是,如果您使用具有大量节点P Btree ,您将获得向量的局部性和内存效率,具有索引的O(logN)读取速度,并将WRITES的数量限制为O(P)而不是O(N)。我从16的P开始,然后使用二分搜索来优化P

不幸的是,真正的答案是尝试所有这些并以您的用例为基准

答案 4 :(得分:1)

最初的问题并不清楚数据在接收数字时检索的频率,或者如何检索数据(通过索引,只是最小的,只是最大的,或全部,)。 ..)。

一种选择是对链表进行自下而上合并排序的逻辑,它使用一个小的(26到32个元素)引用或指针数组,每个都指向一个列表。 Array [i]是包含(2到幂i)节点的列表的引用或指针,array [0]指向大小为1的列表,array [1] - >大小为2的列表,数组[2] - >大小为4的列表,数组的最后一个成员指向列表大小不限的列表。节点一次一个地插入阵列中,这对应于一次接收一个数字。

问题是数据存储在列表数组中,因此只进行了部分排序。要获得完全排序的列表,列表数组将合并到单个列表中。通常只有在将所有数据存储到数组中之后才会这样做。

Wiki链接列表中自下而上合并排序的文章:

http://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation_using_lists

此方法提供快速的平均插入时间,偶尔会长时间。每个其他数字只存储在数组[0]中。 2个边界的功率输入涉及多个合并步骤,第16个输入最终合并两个8个数字的列表,第1024个输入最终合并两个512个数字的列表。

如前所述,二元搜索树(偶尔重新平衡)可能是更好的解决方案。

答案 5 :(得分:0)

它取决于你想如何使用结果。

例如:如果您输入大量数字,并且使用BST存储它们,则需要超过1000步才能找到索引1000.如果将排序结果存储在数组中,则只需要1 step(返回索引[1000])。

如果您只需要最高或最低的数字,然后将其从列表中删除。在那之后你需要下一个最高或最低的数字,你的堆快得多。

还要记住,如果以某种方式对随机数进行排序,则BST看起来像一个列表,然后你没有O(log n)但是O(n)用于插入。

还有很多事情需要考虑。所以请告诉我们您需要什么