我的一位同事今天下午将这个问题悬空,让我感到好奇。我精通排序algos,但缺乏compsci / compeng的正式学位(我有点厌恶承认),不能真正指责这一点。 :P
哦,是的,这在C#/ .NET实现的上下文中是温和的......以防万一会改变一些事情。
谢谢你们。 :)
答案 0 :(得分:10)
对于固定长度的数字,您不限于基于比较的排序算法,因此O(n*log(n))
不限制。 Radix Sort适用于O(n)
,由于IEEE 754浮点数在其位模式被解释为整数时正确排序,因此可以非常方便地使用。
答案 1 :(得分:3)
我看到没有人提到introsort,当递归深度超过某个阈值时,通过切换到heapsort来解决快速排序的O(n^2)
最坏情况。这意味着快速排序不会有机会退化,因为它的递归调用次数肯定会受到限制。
另一个优化是,只要您当前所在序列的元素数量很少(例如16),就切换到insertion sort。
这就是内省的看法:
void Introsort(int A[], int N, int left, int right, int depth)
{
if ( left < right ) // note: this doesn't switch to insertion sort if right - left is small enough
{
if ( (1 << depth) > N )
Heapsort(A, left, right);
else
{
int P = Partition(A, left, right);
Introsort(A, N, left, P, depth+1);
Introsort(A, N, P+1, right, depth+1);
}
}
}
结合良好的分区功能(简单地随机选择枢轴应该足以满足大多数目的),将为您提供一种非常快速的排序算法。
还有radix sort的选择,它的效果非常好,特别是如果你的花车不是太大的话。从我所看到的情况来看,基数排序需要数百万个元素才能超越内省。
答案 2 :(得分:1)
答案 3 :(得分:1)
从理论上讲,您使用big O notation比较算法,这可以让您比较哪种算法对于“几乎无限”的问题更快。在大多数情况下,在实践中,这是比较算法在现实生活中的表现的非常好的观点。
两种最流行的快速排序算法是MergeSort和快速排序。对于任何数据,合并排序保证为O(n log n),而快速排序的平均时间为O(n log n)和悲观时间O(n ^ 2)。在实践中,大多数人使用快速排序,因为:
总而言之,我认为对你的随机浮点数快速排序会更快,即使只看O符号看起来更糟糕 - 因为你会得到预期的O(n log n)并且它的常数会小于合并排序。
答案 4 :(得分:1)
要注意的一个小问题是,如果你的任何一个集合是nan,则该集合不是有序的,并且一些排序算法可能会产生意外结果甚至崩溃。 我认为最好确保在排序之前你的数字都没有。
例如(使用gcc 3.4.6)将qsort(升序)应用于{2,1,nan,-1}给出{1,2,nan,-1}。
另一方面,inf和-inf不是问题。