当使用特定的排序算法而不是其他排序算法时,有哪些用例?合并排序,快速排序,堆排序与“引入排序”等?
是否有根据大小,数据结构类型,可用内存和缓存以及CPU性能使用它们的推荐指南?
当使用特定的排序算法而不是其他排序算法时,有哪些用例?合并排序,快速排序,堆排序与“引入排序”等?
是否有根据大小,数据结构类型,可用内存和缓存以及CPU性能使用它们的推荐指南?
Answers:
首先,一个定义,因为它非常重要:稳定排序是一种保证不会对具有相同键的元素重新排序的排序。
建议:
快速排序: 当您不需要稳定排序时,平均情况下的性能比最坏情况下的性能更重要。快速排序平均为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是基数位数。
桶排序: 可以保证您的输入近似均匀地分布时。
通常,Quicksort通常是最快的,但是它有一些非常讨厌的最坏情况。因此,如果您必须保证没有不良数据提供给您O(N^2)
,则应避免这种情况。
合并排序使用了额外的内存,但是特别适合于外部排序(即,无法容纳在内存中的大文件)。
堆排序可以就地排序,并且没有最坏情况的二次行为,但是在大多数情况下,平均而言,堆排序要比快速排序慢。
如果只涉及有限范围内的整数,则可以使用某种基数排序使其变得非常快。
在99%的情况下,您通常会选择基于quicksort的库排序。
Wikipedia页面上的排序算法具有很好的比较表。
http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms
提供的比较/动画链接不会考虑的是,当数据量超过可用内存时,此时,数据的传递次数(即I / O成本)决定了运行时间。如果需要这样做,请阅读“外部排序”,其中通常涉及合并和堆排序的变体。
http://corte.si/posts/code/visualisingsorting/index.html和http://corte.si/posts/code/timsort/index.html也有一些很酷的图像,它们比较了各种排序算法。
@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),请参见: Java数组是否具有最大大小?
我还要解释一下,对于n个键(其字长为w的整数),基数排序复杂度为O(wn)。有时w被表示为一个常数,这将使基数排序(对于足够大的n而言)比基于最佳比较的最佳排序算法更好,后者均执行O(n log n)比较以对n个键进行排序。但是,通常不能将w视为常数:如果所有n个键都是不同的,则w必须至少为log n才能使随机存取机器能够将其存储在内存中,这充其量是最大的时间复杂度O (n log n)。(来自维基百科)