排序算法总结

首先总结
《排序算法总结》

1.冒泡排序(依次比较/交换相邻的两个元素,进行多趟)

一趟冒泡:(n-1次比较)
1跟2比较,交换;2跟3比较,交换;3跟4比较,交换。。。。。。最后得到一个最值放在末尾处,然后它就不动了。
对剩下的n-1个元素进行第二趟:(n-2次比较)
1跟2比较,交换;2跟3比较,交换;3跟4比较,交换。。。。。。得到一个最值放在倒数第二个位置,不动了。
对剩下的n-2个元素进行第三趟:(n-3次比较)
。。。
对剩下的2个元素进行第n-1趟:(1次比较)

最终比较/交换次数为
(n-1)+(n-2)+(n-3)+(n-4)+ … +1 = n(n-1)/2 =O(n2)

1.1改进的冒泡排序

加入标识符,若一趟下来没有交换,则说明已经排好,平均时间减半,(n^2)/2

2.插入排序(把后面的元素往前面插)

第一趟:(1次比较,[0,3]次元素移动)//要么不移,一移就是3个语句,移动需要一个临时变量
把第2个元素往第1个元素里插,要么放在它前面,要么放在它后面
第二趟:([1,2]次比较,[0,4]次元素移动)
把第3个元素往前2个元素里插,其实就是依次与前面2个元素比较,然后插在合适的位置。
第三趟:([1,3]次比较,[0,5]次元素移动)
把第4个元素往前3个元素里插,依次与前面3个元素比较,然后插在合适的位置。
。。。
第n-1趟:([1,n-1]次比较,[0,n+1]次元素移动)
把第n个元素往前n-1个元素里插,依次与前面n-1个元素比较,然后插在合适的位置。

最好情况
n次比较 + 0次移动语句
最坏情况
(n-1)+(n-2)+(n-3)+(n-4)+ … +1 = n(n-1)/2次比较+
(n+1)+(n)+(n-1)+(n-2)+ … +3 = (n+4)(n-1)/2次移动语句
复杂度为O(n2)

2.1改进插入排序(使用折半查找代替挨个比较)

本来是n趟,每次比较O(n)次
改进后是n趟,每次比较O(log2n)次,因为使用了折半查找
所以复杂度变为O(nlog2n)
适用于n较大并且初始元素比较杂乱的情况,若初始元素接近有序时,使用直接插入会更好。

3.快速排序(分区排序,不稳定)

第一趟:
把第一个元素拎出来,和后面的每个元素进行比较,比它大放左边,比它小放右边,这样就分成了左右两个队列。
第二趟:
对左右两个对列进行同样的操作,拎出第一个元素,继续分

这是一个递归调用
时间复杂度为O(nlog2n)
如果待排序队列本身有序,反而会退化成n(n-1)/2,这是因为递归树变成了单支树
快排水很深,有一些改进方法

4.选择排序(找最值,然后扔掉,不稳定)

4.1直接选择排序

第一趟,在n个元素里找最小值,放到第1位,不管了(n-1次比较,[0,3]次移动)
第二趟,在剩下的n-1个元素里找最小值,放到第2位,不管了(n-2次比较,[0,3]次移动)
第三趟,在剩下的n-2个元素里找最小值,放到第3位,不管了(n-3次比较,[0,3]次移动)
。。。
第n-1趟,在剩下的2个元素里找最小值,放到第n-1位,结束(1次比较,[0,3]次移动)

又是从1加到n-1,(n-1)+(n-2)+(n-3)+(n-4)+ … +1 = n(n-1)/2次比较
但它的比较次数是恒定的,而移动语句的次数最好为0,最坏为3(n-1)
适合于元素很多,但元素占用空间很小的情况,移动起来很快的那种。
复杂度O(n2)

4.2堆排序(通过建立大顶堆的方式找最值)

首先建立大顶堆(所有的父节点都比子节点要大)
然后把最大扔掉(其实是与老末交换),把老末(末尾的元素,不一定是最小的)提上来,放到根节点,重新建立大顶堆,然后就找到了第二大的元素,然后这样继续下去。
将表转化为堆的时间复杂度为O(n)
之后要建立n-1次大顶堆,每一次复杂度为O(log2n)
因此时间复杂度为O(nlog2n)

5.希尔排序(gap,不稳定)

使用gap=gap/2或gap=gap/3+1,把队列分为间隔为gap的gap个小队列。
特点是充分利用直接插入排序的特性:
1)适用于元素少的队列
2)适用于基本有序的队列

对每个小队列使用直接插入排序。一开始gap大,每个小队列元素少,直接插入排序快。之后随着gap变小,每个小队列元素大,但已经基本有序了,直接插入也很快。

6.归并排序(稳定)

先两两比较,合成一个个小队列,再把这些小队列两两比较(把后面的每个元素一次往前面插),这样不断进行指导最终合并成一个
需要一个与元素组一样大的辅助空间
时间复杂度为O(nlog2n),不随初始队列的情况改变。

点赞