排序方法 | 平均 | 最坏 | 最好 | 空间 | 稳定性 |
---|---|---|---|---|---|
直接插入排序 | O(n2)O(n^2)O(n2) | O(n2)O(n^2)O(n2) | O(n)O(n)O(n) | O(1)O(1)O(1) | 稳定 |
希尔排序 | O(n2)O(n^2)O(n2) | O(n)O(n)O(n) | O(1)O(1)O(1) | 不稳定 | |
简单选择排序 | O(n2)O(n^2)O(n2) | O(n2)O(n^2)O(n2) | O(n2)O(n^2)O(n2) | O(1)O(1)O(1) | 不稳定 |
堆排序 | O(nlogn)O(nlogn)O(nlogn) | O(nlogn)O(nlogn)O(nlogn) | O(nlogn)O(nlogn)O(nlogn) | O(1)O(1)O(1) | 不稳定 |
冒泡排序 | O(n2)O(n^2)O(n2) | O(n2)O(n^2)O(n2) | O(n)O(n)O(n) | O(1)O(1)O(1) | 稳定 |
快速排序 | O(nlogn)O(nlogn)O(nlogn) | O(n2)O(n^2)O(n2) | O(nlogn)O(nlogn)O(nlogn) | O(logn)O(logn)O(logn) | 不稳定 |
归并排序 | O(nlogn)O(nlogn)O(nlogn) | O(nlogn)O(nlogn)O(nlogn) | O(nlogn)O(nlogn)O(nlogn) | O(n)O(n)O(n) | 稳定 |
基数排序 | O(d(n+r))O(d(n+r))O(d(n+r)) | O(d(n+r))O(d(n+r))O(d(n+r)) | O(d(n+r))O(d(n+r))O(d(n+r)) | O(r)O(r)O(r) | 稳定 |
一.简单分类
- 简单排序:直接插入,简单选择,冒泡排序——O(n2)O(n^2)O(n2)
- 复杂排序: 堆排序,快速排序,归并排序——O(nlogn)O(nlogn)O(nlogn),基数排序O(d(n+r))O(d(n+r))O(d(n+r)),希尔排序(—)
二.稳定性:
- 稳定 \;\;\;:直接插入,冒泡,归并,基数
- 不稳定: 希尔,简单选择,堆排,快排
三.每趟都能将一个元素放到最终位置:——(选择排序、交换排序)
5. 简单选择、堆排序、冒泡排序——最小值
6. 快排——枢轴pivot
四.平均、最好、最坏相同 (即与初始状态无关):
- 简单选择:O(n2),O(n2),O(n2)O(n^2),O(n^2),O(n^2)O(n2),O(n2),O(n2)
- 归并排序、堆排序:O(nlogn),O(nlogn),O(nlogn)O(nlogn),O(nlogn),O(nlogn)O(nlogn),O(nlogn),O(nlogn)
- 基数排序:O(d(n+r)),O(d(n+r)),O(d(n+r))O(d(n+r)),O(d(n+r)),O(d(n+r))O(d(n+r)),O(d(n+r)),O(d(n+r))
与初始状态有关:
- 直接插入,冒泡排序:正序O(n)O(n)O(n),其他O(n2)O(n^2)O(n2)
- 快排:\qquad正序O(n2)O(n^2)O(n2),其他O(nlogn)O(nlogn)O(nlogn)
- 希尔排序:正序O(n)O(n)O(n)
五.复杂度相同的排序:
- 直接插入= 冒泡排序:O(n2),O(n2),O(n)O(n^2),O(n^2),O(n)O(n2),O(n2),O(n)
- 堆排序 = 归并排序:O(nlogn),O(nlogn),O(nlogn)O(nlogn),O(nlogn),O(nlogn)O(nlogn),O(nlogn),O(nlogn)
六.空间
- 插入排序+希尔排序,选择排序+堆排,冒泡排序:O(1)O(1)O(1)
- 快排:O(logn)O(logn)O(logn)(递归栈)
- 归并:O(n)O(n)O(n)(辅助数组O(n),递归为O(logn)O(logn)O(logn),O(n)+O(logn)=O(n)O(n)+O(logn)=O(n)O(n)+O(logn)=O(n))
- 基数:O(r)O(r)O(r) (radix进制,r个队列)
六.(分治法)递归进行的:
快排、归并
各种排序算法的实测:
比较排序的极限:O(nlogn)O(nlogn)O(nlogn)
分配排序的极限:O(n)O(n)O(n)
排序算法 | 1000000个数(%1000000) | 50000个数 (%50000) |
---|---|---|
冒泡排序 | 5 | 5 |
简单选择排序 | 2.2 | 2.3 |
直接插入排序 | 1 | 1.2 |
希尔排序 | 0.045 | 0.010 |
堆排序 | 0.065 | 0.020 |
归并排序 | 0.033 | 0.030 |
快速排序 | 0.022 | 0.006 |
基数排序 | 0.011 | 0.004 |
- 基数 >>> 快排 >>> (归并∼\sim∼ 堆排 ∼\sim∼希尔) >>> 直接插入 >>> 简单选择 >>>>>>>>> 冒泡排序
- 冒泡排序:可以说是最拉稀的排序,全面拉稀于其他排序。其实可以理解,因为冒泡做了太多的低效的相邻位比较+移动,同样每次选出最小数,冒泡n-1次比较,一次交换就要3次赋值,简单选择也是n-1次比较,但全程只需一次交换就达到同样的目的…冒泡那一堆移动一位的交换简直太低效了,并且对整体的熵值减少(贡献)极低…令人发指
- 快速排序:(比较排序)内部排序中平均时间复杂度最低!虽然同时O(nlogn)O(nlogn)O(nlogn),但是快排明显快于堆排、归并。
- 希尔排序:我们发现希尔排序的效率很高,和O(nlogn)O(nlogn)O(nlogn)的一众算法不相上下,甚至更快。
测试数据:
-
函数内申请的变量,数组,是在栈(stack)中申请的一段连续的空间。栈的默认大小为2M或1M。
-
全局变量,全局数组,静态数组(static)则是开在全局区(静态区)(static)。大小为2G,所以能够开的很大。
-
malloc、new出的空间,则是开在堆(heap)的一段不连续的空间,理论上是硬盘大小。
在函数内定义数组,是局部变量,存放在栈上,一般默认栈的内存是1M,一个int型数字占4byte,1M/4byte=2204=218=2621441M/4byte=\frac{2^{20}}{4}=2^{18}=2621441M/4byte=4220=218=262144个,即