为什么我们总是使用快速排序?或任何特定的排序算法??
我在我的电脑上尝试了一些使用快速,合并,堆,闪存排序的实验
的结果: -
排序算法:以纳秒为单位的时间 - >时间以分钟为单位
快速排序时间:135057597441 - > 2.25095995735
Flash排序时间:137704213630 - > 2.29507022716667
合并排序时间:138317794813 - > 2.30529658021667
堆排序时间:148662032992 - > 2.47770054986667
在内置函数中使用java
long startTime = System.nanoTime();
给定时间以纳秒为单位,如果我们将它们转换为秒为20000000随机整数数据并且在java中最大数组大小为2147483647,则它们之间几乎没有任何差异。如果我们使用就地算法那么可能存在1到1的差异2分钟直到最大阵列大小。
如果差异太小我们为什么要关心?
答案 0 :(得分:7)
所有呈现的算法都有类似的平均大小范围,O(n lg n)
,这是comparison sort可以做的“最佳”。
由于它们共享相同的平均界限,因此这些算法相对于随机数据的预期性能应该相似 - 这就是调查结果所显示的。然而,魔鬼在细节中。这是一个非常快速的总结;请点击链接了解更多详情。
Quicksort通常不稳定(但有stable variations)。虽然quicksort的平均界限为O(n lg n)
,但Quicksort的最差情况界限为O(n * n)
,但有一些方法可以缓解此问题。像heapsort一样,Quicksort已经就地完成。
Merge-sort是stable sort。 Mergesort的最坏情况界限为O(n lg n)
,这意味着它具有可预测的性能。基本合并排序需要O(n)
额外空间,因此它通常不就地排序(尽管有in-place variant,并且链表实现的内存是常量)
Heapsort 不稳定;它也具有O(n lg n)
的最坏情况界限,但具有恒定大小边界和就地的好处。它比cache-sort具有更糟糕的缓存和并行性方面。
究竟哪一个是“最好的”取决于用例,数据和确切的实现/变体。
Merge-sort(或hybrid such as Timsort)是许多库/语言中的“默认”排序实现。在几个C ++实现中使用了一个公共Quicksort-based hybrid, Introsort。如果提供Vanilla / plain Quicksort实现,通常是次要实现。
Merge-sort:具有一致性能和可接受内存限制的稳定排序。
Quicksort / heapsort:轻松地就地,[有效]不需要额外的内存。
答案 1 :(得分:2)
我们很少需要对整数数据进行排序。排序中最大的开销之一是进行比较所需的时间。 Quicksort通过与冒泡排序进行比较来减少所需的比较次数。如果你正在排序字符串,那就更重要了。几年前,作为一个现实世界的例子,我写了一个排序/合并,用泡泡排序花了40分钟,快速排序了17分钟。 (很久以前它是一台z80 CPU。我现在期待更好的性能)。
答案 2 :(得分:1)
你的结论是正确的:在大多数情况下,大多数关心这一点的人都会浪费时间。在时间和内存复杂性方面,这些算法之间的差异在以下特定情况下变得非常重要:
您需要排序大量元素
性能非常至关重要(例如:实时系统)
资源确实有限(例如:嵌入式系统)
(请注意真的)
此外,人们担心稳定性可能更为重要。大多数标准库提供稳定的排序算法(例如:C#中的OrderBy
,C ++中的std::stable_sort
,Python中的sort
,Java中的sort
方法。
答案 3 :(得分:0)
正确性。虽然在某些特定情况下在排序算法之间进行切换可能会提高速度,但证明算法起作用的成本可能会很高。
例如,TimSort是Android,Java和Python使用的一种流行的排序算法,它的实现错误多年来一直未被人注意。该错误可能导致崩溃,并且很容易被用户引起。
需要一个专门的团队“寻找挑战”来isolate and solve问题。
由于这个原因,只要有可用的数据结构或算法的标准实现,我都会使用该标准实现。使用更智能的实现节省的时间很少值得不确定实现的安全性和正确性。