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

Algorithm 连续(非固定)输入随机数的最佳排序算法是什么?,algorithm,sorting,data-structures,binary-tree,binary-search-tree,Algorithm,Sorting,Data Structures,Binary Tree,Binary Search Tree,假设我有一个系统,它一个接一个地接收连续不断的随机数作为输入(0,5,2,10,6,20…) 我的目的是以最佳性能对它们进行排序 因此,每次迭代后,输出大小都会增加,并且输入是连续的 我想使用插入排序或BST,但我不确定对于这个问题什么更好,因为我知道插入排序是O(n-n^2),而BST插入是O(log(n)) 请,有什么建议吗?插入排序对于小输入(小于1000)是有效的,否则因为它需要O(n^2)的运行时间,所以复杂性会增长得非常快,如果您不确定输入会增长到多大,那么请使用运行时间比O(n^2

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

我的目的是以最佳性能对它们进行排序

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

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


请,有什么建议吗?

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

这取决于您希望如何使用结果

例如:如果您输入了很多数字,并且使用BST存储它们,则需要1000多个步骤才能找到索引1000。如果将排序结果存储在数组中,则只需要一个步骤(返回索引[1000])

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

还请记住,如果随机数以某种方式排序,BST看起来像一个列表,那么插入时没有O(logn),只有O(n)


你还有很多事情要考虑。因此,请告诉我们您需要这个什么

我认为使用一些承诺
O(logn)
performacne(如AVL、黑红色等)的BST是您最好的选择


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

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

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

如果你有更多的自由,BST确实是一个更有效的解决方案。如果您需要绝对保证最坏情况下的成本(O(logn)),则BST需要平衡(因此AVL、红黑…取决于您的喜好)。如果您的数据足够随机,这可能是不必要的


如果数据具有特殊属性(例如小的离散范围),则临时解决方案可以。在给定的示例中,一个简单的计数直方图将实现O(1)更新时间。

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

  • 找到插入点的读取数
  • 写入次数(如移位、重新平衡)插入
  • 总内存/位置(影响缓存未命中)常量(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()的其他溶液的常数明显更高

最佳解决方案可以根据当前的体系结构约束而变化。如果内存/缓存大小很小,则排序向量可能是最佳的。 如果分支未命中的代价很高,则链接列表可能是最佳的,因为除最后一个分支外,其他分支都将是错误的

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


不幸的是,真正的答案是全部尝试,并用您的用例进行基准测试。最初的问题并没有明确说明在接收数字时数据必须检索的频率,或者如何检索数字(按索引、最小值、最大值或全部等)

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

问题是数据存储在列表数组中,因此只能部分排序。要获得完全排序的列表,列表数组将合并到单个列表中。通常,只有在将所有数据存储到阵列中后才能执行此操作

链接列表上自底向上合并排序的Wiki文章:

这种方法提供了快速的平均插入时间,有时插入时间较长。每隔一个数字就存储到数组[0]中。两个边界幂的输入涉及多个合并步骤,第16个输入最终合并两个8个数字的列表,第1024个输入最终合并两个512个数字的列表


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

如果您想根据到达时间对它们进行排序,只需将每个新数字添加到列表的末尾……我编辑了我的问题,我只想对它们进行排序(0,2,5,6…)O(n-n^2)的含义是什么?@Yves Daoust插入排序:最好的是O(n) 使用skiplist的最坏情况O(n^2)将为插入提供O(logn)为什么不使用一些BST(AVL,黑红色,e