主要针对于插入排序,交换(冒泡和快速),选择,堆排序,归并这几种排序的基本原理和时间复杂度,及空间复杂度的一个总结。
一、插入排序
基本执行过程:3 5 2 7 9 8
1、从小到大:从第二个数开始,每次比较都与前边的几个数进行比较
但是从大到小,要先与前边排好序的几个数中的最大的开始进行比较即倒序比较,依次往前推。
如:5 先与3进行比较,比3大,所以直接排在3的后边为:3
5;
2要先与5进行比较,比5小,再与3比较,比3小,所以排序后为 2
3 5;
7要先与5比,比5大,所以直接排在5后边即可 ,为 2
3 5 7;
2、从大到小:按从小到大:每次比较与最小的先进行比较(倒序),
如:5先与3比,比3大,所以放在3的前面 为:5
3;
2要先与3比,比3小,所以直接为 5
3 2;依次这样比较即可
3、时间复杂度:
最优:当给出的几个数,已经有序时,比如 1 2 3 4 5,那么只需要n-1次,所以时间复杂度为O(n),与n有关
最差:如果给出的几个数与要排序的次序全部相反时,那么每次比较时,从第二个数开始,分别需要比较1 , 2,……(n-1) 次,即时间复杂度为1+2+…+(n-1)=
n(n-1)/2,所以为O(n2)
4、空间复杂度
每次比较,只需要一个辅助空间用来将两个数进行交换,所以为O(1)
二、冒泡 (从小到大举例)
3 5 2 7 9 8
1、基本执行过程:每次比较都选出一个最大的值,沉底
第一个数沉底:3 与5 比,5大,所以为3,5;
5与2比,5大,将5放在2的位置:3,2,5;
5与7比,7大,3,2,5,7;
7与9比,9大,3,2,5,7,9
9与8比,9大,把9放在8的位置,为3,2,5,7,8,9;
此时,第一个数沉底的过程执行完毕。
依次类推,
2、时间复杂度:每次冒泡排序,理论上应执行i=1 to n-1趟(每趟选出一个最大的树沉底),而每趟比较时,需要比较n-i 次(找第一个数比较n-1次,第二个比较n-2次,第i个需n-i次),所以每一个冒泡排序需要两层循环,每层循环都与n有关,所以时间复杂度为O(n2)
最好:已经排好序的一组数,只需要执行n-1次即可所以最好时为O(n)
3、空间复杂度:同上O(1)
三、快速排序
38(low) 66 90 88 10 25 45(high)
1、基本执行过程:
每次比较将第一个数存放起来,作为标志数 x=38保存起来
同时,从第一个和最后一个数开始,分别作为最低和最高标志数的位置
第一趟:从high(45)开始,向前找比x值小的数,直到找到为止,这里为25,与Low位置的数进行交换此时为25(low) 66
90 88 10 38(high) 45
然后从Low开始往后继续找比x值大的数,直到找到为止,这里为66,与high(38)进行交换为 25
38(low) 90 88 10 66(high) 45
依次类推,直到一组数,以x为中介,左边的都比x小,右边的都比x大时,第一趟比较结束。
第二趟开始,将分好的两组继续按第一趟的步骤分别进行比较。
2、时间复杂度
每次执行都把n个数分为两半
第一次执行T(n)=O(n) :O(n)=n
第二次执行T(n)=O(n)+2T(n/2) :T(n/2)代表分成两半以后,每一半时间复杂度
将第二次执行中的n/2看做为n,那么第三次执行后T(n)=O(n)+2T(n/2),其实,这是一个递归式。
所以根据算法定理
T(n)=aT(n/b)+fn
即,这里的a=2,b=2 ,fn=n
a=b的k次幂,所以T(n)=O(nlogbn)=O(nLog2n)
这个时间复杂度和折半查找以及归并排序类似,可以自己联系一下
四、 选择排序
与冒泡排序正好相反:每排序一趟,把序列中最小的数依次放到序列的最前面
先假设第一个数为最小的,依次与第2,3,4。。。n个数进行比较,没遇到一个比自己小的数,就进行交换,始终保持第一个数为最小的,此为第一趟
时间复杂度:i=n-1趟(找第几个最小的数)
每一趟都从比较的第i个数的后一个开始进行比较,直到n
所以也是两层循环,每层都与n有关为O(n2)
空间复杂度:O(1)
五 、堆排序
2 5 3 6 8 9 7
基本执行过程
1、首先将给出的数列进行建树,按顺序建成二叉排序树就好了
2、将建好的二叉树调整成大堆(从大到小)或者小堆(从小到大),从[n/2](这里的n/2的孩子节点为叶子节点)向下取整开始,进行调整,不符合的与父节点进行条换
3、建好堆后,将根节点与最后一个子节点进行交换,交换后,将最后一个子节点拿出,此时为最大值(大堆)或最小值(小堆)
4、按照第二步再进行调整堆,再交换,依次进行即可
如图:
1、建二叉树:
2、调整堆
从第3个节点开始进行调整
上面这个树不需要进行调整,因为满足建立一个小堆的要求
3、交换
将2和7进行交换
然后第一个数就出来了为2
4、再调整堆为最小的,此时还是从6/2 =3第3个数开始进行调整调整为一个小堆
5、再交换
3和9交换,此时第二个数3就出来了
依次向上面这样进行排序就好了
时间复杂度:每次去一个数,所以共需n-1趟
每趟比较时,进行调整堆,需要比较最多为树的深度次为[Log2n]+1次
所以时间复杂度为O(nLog2n)
空间复杂度:O(1)
六 、归并排序
2 5 4 7 4 8 9
基本执行过程:先两两合并进行比较,从小到大
[2,5] [4,7] [4,8] 9
再让相邻的的两组合并然后进行比较:
[2,5]与[4,7]比较 2与4比较,2小,取出,5与4比较,4小,取出,5与7比较,5小,取出,此时这四个数排好后为:2,4,5,7
然后再比较[4,8] 9
最后再让两组合并比较即可
时间复杂度:与快速排序原理一致,正好是快速排序倒过来的思路最后结果仍为O(nLog2n)
空间复杂度:O(n)???????不太确定??
以上是几种常用的排序算法:
小结:当数组元素基本有序时,采用插入和冒泡排序 O(n)
当n很大时,采用快速,堆,归并排序
稳定排序:插入,冒泡,归并
不稳定:快速,选择,堆排序