O(n²): 插入排序 , 冒泡排序 , 选择排序.
O(nlgn): 快速排序, 堆排序 , 归并排序
高级排序: 希尔排序 , 基数排序..
---------------------------------------------------------------------------------------------------------------------
插入排序<insert sort>(折半插入排序)
[5 7 6 9 8 7 4 0 4]
[5] 7 6 9 8 7 4 0 4]
[5 7] 6 9 8 7 4 0 4] 拿出7,与有序逐一比较,插入
↘
[5 6 7] 9 8 7 4 0 4] 拿出6与有序逐一比较,插入
[5 6 7 9] 8 7 4 0 4]
↘
[5 6 7 8 9] 7 4 0 4]
↘↘
[5 6 7 7 8 9] 4 0 4]
↘↘↘↘↘
[4 5 6 7 7 8 9] 0 4]
[0 4 5 6 7 7 8 9] 4]
[0 4 4 5 6 7 7 8 9]
(折半插入排序,又称二分插入排序.跟插入排序一样,只不过比较插入的时候是用low,high的一半求middle来比较的
---------------------------------------------------------------------------------------------------------------------
希尔排序<shell>(插入排序优化版)
[5 7 6 9 8 7 4 0 4] d=n/2=4
[4 7 4 0 5 7 6 9 8] a[0]的5与a[4]的8,a[8]的4成一组比较,a[1]与a[5]比较,a[2]与a[6]比较..
[4 0 4 7 5 7 6 9 8] a[0]与a[2],a[4],a[6],a[8]成一组比较,a[1]与a[3],a[5],a[7].....
[0 4 4 5 6 7 7 8 9]
---------------------------------------------------------------------------------------------------------------------
冒泡排序<bubble sort>(白色字体为加了监视哨的优化)
[5 7 6 9 8 7 4 0 4]
0 [5 7 6 9 8 7 4 4] 最后交换的位置在a[1],下次得循环到下标1
0 4 [5 7 6 9 8 7 4] 最后交换的位置在a[2],下次得循环到下标2
0 4 4 [5 7 6 9 8 7] 最后交换的位置在a[3],下次得循环到下标3
0 4 4 5 [6 7 7 9 8] 最后交换的位置在a[5],下次得循环到下标5
0 4 4 5 6 [7 7 8 9] 最后交换的位置在a[8],下次得循环到下标8
如果带有记录上一次交换的下标记录,这里可以结束了
0 4 4 5 6 7 7 8 9
---------------------------------------------------------------------------------------------------------------------
快速排序<quick sort>
[5 7 6 9 8 7 4 0 4] 选出a[0]的5作为标准将数组分堆.
第一次分:
4 [7 6 9 8 7 4 0 5] 5和最后面比较,直到找到比自己小,就交换
4 [5 6 9 8 7 4 0 ] 7 5和最前面比较,直到找到比自己大,就交换
4 0 [6 9 8 7 4 5] 7 5和最后面比较,直到找到比自己小,就交换
4 0 [5 9 8 7 4 ]6 7
4 0 4 [9 8 7 5] 6 7
4 04 [5 8 7] 9 6 7
[4 0 4] 5 [ 8 7 9 6 7] 以5分标准分两边
对5的前部分再来快速排序:
0 4 4 以开头的4为标准分两边
对5的后部分再来快速排序:
7 [7 9 6 8]
7 7 [8 6] 9
7 7 6 [8] 9 以开头的8为标准分两边
对8的前部分再快速排序:
6 7 7 以开头的7为标准
得到 0 4 4 6 7 7 8 9
感觉我这个序列对于快速排序来说还真是可惜了....在第一趟竟然没有碰头
---------------------------------------------------------------------------------------------------------------------
选择排序<select sort>
[5 7 6 9 8 7 4 0 4] 选出最小0, a[0]的5与0位置交换
0 [7 6 9 8 7 4 5 4] 选出最小4, a[1]的7与4位置交换
0 4 [6 9 8 7 7 5 4] ...
0 4 4 [9 8 7 7 5 6]
0 4 4 5 [8 7 7 9 6]
0 4 4 5 6 [7 7 9 8]
0 4 4 5 6 7 [7 9 8]
0 4 4 5 6 7 7 [9 8]
0 4 4 5 6 7 7 8 9]
---------------------------------------------------------------------------------------------------------------------
堆排序<heap sort>
[5 7 6 9 8 7 4 0 4]...
建成小栈堆 这个堆的序列是[04 5 4 8 7 6 97]
取走0(顶元素),用最后一个替上,变成,失去小栈堆的平衡,再变:
取走4(顶元素),用最后一个替上,变成,失去小栈堆的平衡,再变:
取走4(顶元素),用最后一个替上,,失去小栈堆的平衡,再变:
取走5,用7替上......................................
最后得到序列[0 4 4 5 6 7 78 9]
---------------------------------------------------------------------------------------------------------------------
归并排序<merge sort>
[5 7 6 9 8 7 4 0 4]
[5 7 6 9] [8 7 4 0 4] 对半分组
[5 7] [6 9] [8 7] [4 0 4] 对半分组
[5] [7] [6] [9] [8] [7] [4] [0] [4] 对半分组
[5 7] [6 9] [7 8] [0 4] [4] 5,7排序/6,9排序/8,7排序//4,0排序
[5 6 7 9] [0 4 7 8] [4] 指针a指向第一组第一个指针,b指向第二组第一个.(例如a指向[5,7]的5,b指向[6,9]的6)然后两指针比较
[0 4 5 67 7 8 9] [4] 指针小的进组,然后指向下一个继续比较(5进组,a指向下一个.就是7,b还是指向6,比较,6进组,b指向9)
[0 44 5 6 7 7 8 9] 同上直到成为一个数组,就排好了.稳定的哦.
---------------------------------------------------------------------------------------------------------------------
基数排序<radix sort>
[576 984 704 544 601 435 104 348 343]
先按个位,将大家分到各个位置.
0|||
1||| 601
2|||
3||| 343
4||| 984 704 544 104
5||| 435
6||| 576
7|||
8||| 348
9|||
得到[601 343 984 704 544 104 435 576 348]
按十位,
0||| 601 704 104
1|||
2|||
3||| 435
4||| 343 544 348
5|||
6|||
7||| 576
8||| 984
9|||
得到[601 704 104 435 343 544 348 576 984]
按百位,
0|||
1||| 104
2|||
3||| 343 348
4||| 435
5||| 544 576
6||| 601
7||| 704
8|||
9||| 984
得到[104 343 348 435 544 576 601 704 984]
---------------------------------------------------------------------------------------------------------------------
时间复杂度:
插入排序:
最好时间O(n)...
[1 2 3 4 5 6 7 8 9]. 取出1,[1] 和[2 3 4 5 6 7 8 9].取出2,比较得[1 2]和[3 4 5 6 7 8 9].取出3,比较,插入得出[1 2 3]和[4 5 6 7 8 9]..............每次跟最后一个比较,比它大即插入,只要9次.
最坏时间O(n²)..
.[9 8 7 6 5 4 3 2 1] 取出9.....取出8,比较,9移位.得到[8 9][7 6 5 4 3 2 1]..取出7,比较9,比较8.然后移位.比较2次,移位2次...取出6,比较3次,移位3次//取出1,比较8次,移位8次.
平均时间O(n²)
希尔排序:
最好时间O(n(logn))
[1 2 3 4 5 6 7 8] 第一趟1和5,2和6,3和7,4和8....比较8次..第二趟1,3,5,7//2,4,6,8...比较8次. 第三趟[123456789] 8次~~其实具体要多少趟呢,反正最后一定是分到为1.假设为X趟吧.......
然后最好时间是有序,所以每趟最快为比较n次..所以总时间就是nlogn
最坏时间O(n的s次方) s接近2.
希尔排序是比插入排序快的,所以时间复杂度<o(n²) .最坏情况第一趟也只是比较n +6次.第二趟因为有第一趟的基础已经初步有序了,最坏情况大于n次小于²次..第三趟有了第二趟的基础......
平均时间 经验所得
冒泡排序:
最好时间O(n)
[1 2 3 4 5 6 7 8 9] 设置了记录最后一次交换的监视哨,扫了一遍,监视哨为末尾,即下一次直接可结束
最坏时间O(n²)
没有设置监视哨或者遇到这种情况[9 8 7 6 5 4 3 2 1] ...的确是n²呢
快速排序:
最好时间O(nlogn)
[4 1 3 2 6 5 7 8]→[2 1 3] 4 [ 6 5 7 8]
[2 1 3]→[1] 2 [3]
[ 6 5 7 8]→[5] 6 [ 7 8 ]
第一次,取4,从最后往前扫描寻找比自己小的数来交换,扫描了4次(n/2)得到中间位置,然后从前面往后面扫面寻找比自己大的数交换,结果在中间碰头了,结束一轮排序.
第二轮,2取得中间位置.同时6也取得中间位置.也都是一下子碰头
排序完毕.... 1 2 3 4 5 6 7 8
最快排序就是每次都成功将他分开各一半.
像上面的,8个数可以是2³,就是三轮就可以解决.每次扫描n次
最坏时间O(n²)
[66 6 6 66 6 6] 这样每个数为标准都得对其他数扫一次......第一次,对6比较,假如代码是小于才交换,即对666666 都要扫一次,发现没有,比起小,于是确认6一个.后面的同理,比较次数7+6+5+4+3+2+1
假如代码是小于等于就交换,第一次以6为标准,跟6比较,交换,然后跟6比较,又交换,然后跟6比较,交换....变成[6666]6 [666],第一趟就比较了7次,交换7次了..后面就不说了..
平均时间O(nlogn)
可以说快速排序是基本最快的排序方法~虽然不稳定
选择排序
最好时间&最坏时间&平均时间:都是O(n²)
就算是[1 2 3 4 5 6 7 8]..第一趟也要比较1,2,3,4,5,6,7,8里面谁最小,1最小,放在最前..第二趟比较2,3,4,5,6,7,8谁最小......最简单的排序方法
归并排序
最好时间&最坏时间&平均时间:都是O(nlogn)
就算是[8 7 6 5 4 3 2 1] 会分成[8 7 6 5] [4 3 2 1],再变成[8 7] [6 5] [4 3] [2 1]最后[8][7][6][5][4][3][2][1]
合成先是[7 8][5 6][3 4][1 2],然后[5 6 7 8][1 2 3 4]..最后[1 2 3 4 5 6 7 8]
分解的次数是3次,就是2³=8啦,时间度是logn,插入的时间是O(n),因为已经基本有序,两个指针比较分别插入就OK了.所以总体是O(nlogn)
他的速度仅次于快速排序,但是优势是,它是稳定排序.
至于为啥说还是快速排序快点呢,它们不都是nlogn吗?这个很容易看的,logn大家基本是一样的吧,快速排序是把序列以头个数为标准分成前后两部分,直接到前后两部分为0或1....而归并排序则是不断无脑二分到为一为止.
但是n就不同了,归并排序的n,必须是n,因为要把两组数里面的数全插入去,比如[4 6][5 7],这里n是4,插入4次嘛~~~快速排序则只需要n-1哦,比如[8 7 6 9 5]这5个数以8为标准比较4次就OK了.
堆排序
最好时间&最坏时间&平均时间:都是O(nlogn)
n个数,那么作为二叉树来说,它的高度最多是log(2)n...比如3个节点,高度只能为1~对于根节点,他最多就移动到叶子的位置,也就是移动了logn次.对于第一层 的两个节点,最多就移动logn-1次
这个是初始建堆的时间,总之是O(n)就对了,初始堆已经是小(大)栈堆,然后调堆时最多只需要移动logn次就OK了,因为基本有序而且高度最多 是logn..就这样循环n/2次就可以了
基数排序
n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集。