快速排序 Vs. 归并排序 Vs. 堆排序——谁才是最强的排序算法

知乎上有一个问题是这样的:算法

堆排序是渐进最优的比较排序算法,达到了O(nlgn)这一下界,而快排有必定的可能性会产生最坏划分,时间复杂度可能为O(n^2),那为何快排在实际使用中一般优于堆排序?测试

昨天恰好写了一篇关于快排优化的文章,今天再多作一个比较吧。首先先看一个排序算法图:优化

排序方法 平均状况 最好状况 最坏状况 辅助空间 稳定性
冒泡排序 O(n^2) O(n) O(n^2) O(1) 稳定
简单选择排序 O(n^2) O(n^2) O(n^2) O(1) 稳定
直接插入排序 O(n^2) O(n) O(n^2) O(1) 稳定
希尔排序 O(nlogn)~O(n^2) O(n^1.3) O(n^2) O(1) 不稳定
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定
快速排序 O(nlogn) O(nlogn) O(n^2) O(logn)~O(n) 不稳定

能够看到,到达nlogn级别的排序算法,一共有三种,分别是堆排序,归并排序以及快速排序,其中只有归并排序最稳定。那么,为何要说快速排序的平均状况是最快的呢?code

实际上在算法分析中,大O的做用是给出一个规模的下界,而不是增加数量的下界。所以,算法复杂度同样只是说明随着数据量的增长,算法时间代价增加的趋势相同,并非执行的时间就同样,这里面有不少常量参数的差异,好比在公式里各个排序算法的前面都省略了一个c,这个c对于堆排序来讲是100,可能对于快速排序来讲就是10,但由于是常数级因此不影响大O。排序

另外,即便是一样的算法,不一样的人写的代码,不一样的应用场景下执行时间也可能差异很大。下面是一个测试数据:table

测试的平均排序时间:数据是随机整数,时间单位是s
数据规模    快速排序       归并排序        希尔排序        堆排序
1000万       0.75           1.22          1.77          3.57
5000万       3.78           6.29          9.48         26.54  
1亿          7.65          13.06         18.79         61.31

堆排序每次取一个最大值和堆底部的数据交换,从新筛选堆,把堆顶的X调整到位,有很大多是依旧调整到堆的底部(堆的底部X显然是比较小的数,才会在底部),而后再次和堆顶最大值交换,再调整下来,能够说堆排序作了许多无用功。class

总结起来就是,快排的最坏时间虽然复杂度高,可是在统计意义上,这种数据出现的几率极小,而堆排序过程里的交换跟快排过程里的交换虽然都是常量时间,可是常量时间差不少。方法

相关文章
相关标签/搜索