比较排序
基于插入
1、直接插入排序
概念:理扑克牌。将后面未排好序的数插入到前面已排好的序列中。
时间复杂度:O(n2) O(n) O(n2) (最坏 最好 平均)
空间复杂度(辅助空间):O(1)
稳定
|
发现:接近有序的序列,比较次数小
优化:增量划分组,多次插入排序逐渐接近有序
|
2、希尔排序
概念:增量+分组+插入排序。以i为间隔划分组进行插入排序,i递减。
O(n2) O(n1.3) O(n)
O(1)
不稳定
基于交换
3、冒泡排序
概念:小的数向上冒泡直到遇到小于等于它的。
O(n2) O(n) O(n2)
O(1)
稳定
|
优化:双向进行冒泡,小的放前,大的放后。
|
4、快速排序
概念:双向冒泡排序+分治。以一个数为基准,双向遍历,小的放前,大的放后。再对两边进行相同操作。
O(n2) O(nlogn) O(nlogn)
O(nlogn)用于函数递归栈
不稳定
最坏情况:逆序,退化为冒泡排序
优化方法:
具体内容可参考:https://www.cnblogs.com/vipchenwei/p/7460293.html
1、最坏情况:基本有序时,按普通方式选基准会导致退化。可以使用随机选基准。更优的方式是三数取中:最低位,中位,最高位的三个数中选最小/大(取决于升/逆序)。
2、对于小范围的基本有序序列,插入排序更快。所以向下递归时,判断当前递归数组大小范围小于一定范围时就放弃快排改用插入排序。
3、针对重复率高的序列。一次双向遍历后,在分割前,将之前遍历到的和基准值相同的元素取出来聚在中间,从而使分割后的两个序列变短,减少递归次数。
4、最坏情况时,递归深度接近于n,容易栈溢出。对于某些语言的编译器,可以使用尾递归(将返回结果放入调用参数中,从而可以释放自己而不用入栈,直接返回下一递归函数)的方式防爆栈。提高了鲁棒性。
”尾递归“具体可参考:https://www.cnblogs.com/catch/p/3495450.html
基于选择
5、选择排序
概念:每次选出最小的。
O(n2)
O(1)
不稳定
|
优化:不通过遍历来找最小的,而是维护一个最小堆。
|
6、堆排序
概念:维护一个最小堆,每次选出最小的的。
O(nlog2n)
O(1)
不稳定
7、归并排序
概念:向下递归划分组直到每组一个数,再向上合并。
O(nlog2n)
O(n)
线性排序
8、计数排序
概念:遍历序列,维护一个记录下标数出现次数的数组。序列中数的排序位置即下标小于它的数组前缀和。
O(n)
O(m) m取决于序列中数的范围
稳定
9、桶排序
概念:将数根据映射函数划分至有序的不同桶中,每个桶内部再排序。
O(n+c)
O(n+m)
取决于划分到桶后的排序算法是否稳定
10、基数排序
概念:类似于字符串比大小。从低到最高位,位上的数根据[0,最大基数]进行分组。
O(d(r+n)) O(dr+n) n个记录,d个关键码,关键码的取值范围为r
稳定
常用结论:
最坏(即所有数互相都比过一次)的比较次数为n(n-1)/2
冒泡排序、快速排序、插入排序、希尔排序对数据的有序性敏感
不管有序性,归并、堆:O(nlog2n),选择排序:O(n2)
对于序列长度 比较大的随机序列,应选择平均时间复杂度较小的快速排序方法。
参考:
https://www.cnblogs.com/wxisme/p/5243631.html
https://www.cnblogs.com/jaylon/p/5735431.html
https://blog.csdn.net/hr10707020217/article/details/10581371