特定排序算法优于其他排序算法的用例有哪些 - merge sort
vs quick sort
vs heap sort
vs intro sort
等?
根据大小,数据结构类型,可用内存和缓存以及CPU性能,是否有建议使用它们?
答案 0 :(得分:284)
首先,定义,因为它非常重要:稳定排序是保证不会对具有相同键的元素重新排序的定义。
建议:
快速排序:当您不需要稳定排序时,平均案例性能比最差案例性能更重要。快速排序平均为O(N log N),在最坏的情况下为O(N ^ 2)。一个好的实现使用堆栈空间形式的O(log N)辅助存储进行递归。
合并排序:当您需要稳定的O(N log N)排序时,这是您唯一的选择。唯一的缺点是它使用O(N)辅助空间并且具有比快速排序略大的常数。有一些就地合并排序,但AFAIK它们都不稳定或比O(N log N)更差。即使O(N log N)就地排序也比普通的旧合并排序有更大的常数,它们比有用的算法更具理论上的好奇心。
堆排序:当您不需要稳定排序时,您更关心最坏情况下的性能而非平均情况下的性能。它保证为O(N log N),并使用O(1)辅助空间,这意味着在非常大的输入上不会意外地耗尽堆或堆栈空间。
Introsort:这是一种快速排序,在某个递归深度之后切换到堆排序,以绕过快速排序的O(N ^ 2)最坏情况。它几乎总是比普通的快速排序更好,因为你得到了快速排序的平均情况,并保证了O(N log N)性能。可能使用堆排序而不是使用堆排序的唯一原因是在严重的内存受限系统中,其中O(log N)堆栈空间实际上非常重要。
插入排序:当N保证较小时,包括快速排序或合并排序的基本情况。虽然这是O(N ^ 2),但它具有非常小的常数并且是稳定的排序。
冒泡排序,选择排序:当你做一些快速而又脏的事情时,出于某种原因你不能只使用标准库的排序算法。这些优于插入排序的唯一优势是更容易实现。
非比较排序:在一些相当有限的条件下,可以打破O(N log N)障碍并在O(N)中排序。以下是一些值得一试的案例:
计数排序:当您对有限范围内的整数进行排序时。
基数排序:当log(N)明显大于K时,其中K是基数位数。
水桶分类:当您可以保证输入大致均匀分布时。
答案 1 :(得分:24)
Quicksort 通常是最快的,但它有一些非常讨厌的最坏情况行为。因此,如果您必须保证没有错误数据为您提供O(N^2)
,您应该避免使用它。
Merge-sort 使用额外的内存,但特别适合外部排序(即不适合内存的大文件)。
堆排序可以就地排序,并且没有最坏情况的二次行为,但在大多数情况下,平均速度比快速排序慢。
如果仅涉及限制范围内的整数,则可以使用某种基数排序来使其非常快。
在99%的情况下,您可以使用库存排序,这通常基于快速排序。
答案 2 :(得分:3)
关于排序算法的维基百科页面有一个很好的比较图表。
http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms
答案 3 :(得分:3)
提供的比较/动画链接不考虑的是数据量何时超过可用内存 - 此时数据传递次数(即I / O成本)占据运行时间的主导地位。如果你需要这样做,请阅读“外部排序”,它通常涵盖合并和堆排序的变体。
http://corte.si/posts/code/visualisingsorting/index.html和http://corte.si/posts/code/timsort/index.html也有一些比较各种排序算法的酷图像。
答案 4 :(得分:0)
@dsimcha写道: 计数排序:当您对有限范围的整数进行排序时
我会改为:
计数排序:当你排序正整数时(0 - Integer.MAX_VALUE-2由于鸽舍)。
您也可以始终在线性时间内获得最大值和最小值作为效率启发式 此外,您需要为中间阵列至少增加n个空间,并且它显然是稳定的。
/**
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
(即使它实际上允许MAX_VALUE-2) 看到: Do Java arrays have a maximum size?
我还要解释,对于n个键,基数排序复杂度为O(wn),这是字大小为w的整数。有时w表示为常数,这将使得基数排序比基于比较的最佳排序算法更好(对于足够大的n),所有排序算法都执行O(n log n)比较以排序n个键。但是,通常w不能被认为是常数:如果所有n个密钥都是不同的,则w必须至少为log n,以便随机访问机器能够将它们存储在内存中,这最多会给出时间复杂度O (n log n)。 (来自维基百科)