假设我有一个系统一个接一个地接收连续随机数作为输入(0,5,2,10,6,20......)
,
我的目的是以最佳表现对它们进行排序。
因此,每次迭代后输出大小都会增加,并且输入是连续的。
我想使用插入排序或BST,但我不确定这个问题有什么用处,因为我知道插入排序为O(n-n^2)
,BST插入为O(log(n))
请提出任何建议?
答案 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)
有几个因素会影响解决方案的效率:
请注意,根据数据结构,这些数据的变化会比算法更多,因为随着每个元素的添加,算法似乎始终是插入排序的变体
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)用于插入。
还有很多事情需要考虑。所以请告诉我们您需要什么