【以下所有示例均以從小到大排序爲例】
(一)插入排序
1.直接插入排序
【基本思想】將數列分成有序區和無序區,從無序區中選取一個數與有序區的數依次比較後插入合適的位置,該位置後的有序區記錄依次後移,直到全部記錄排好序。時間複雜度O(n^2)
↓←←←←←←←←←←←←←←←←↑
R1 ≤ R2 ≤ R3 ≤······≤ Ri-1 | Ri , Ri+1 , Ri+2 ,······ , Rn
有序區 無序區
原始數列: [51] 33 62 17 28 51'
第一趟: [33 51] 62 17 28 51'
第二趟: [33 51 62] 17 28 51'
第三趟: [17 33 51 62] 28 51'
第四趟: [17 28 33 51 62] 51'
第五趟: [17 28 33 51 51' 62]
2.折半插入排序
【基本思想】在直接插入排序的基礎上改進,由於前半部分已經是有序數列,在查找插入位置時使用高效率的“折半查找”。
該方法僅減少關鍵字的比較次數,卻沒有減少記錄的移動次數,時間複雜度仍爲O(n^2)
3.二路插入排序
【基本思想】另開一個循環數組d[],將第一個關鍵字R0賦值給d[1],將大於R0的數插入R0之後的有序數組,將小於R0的數插入R0之前的有序數組。需附加n個記錄的輔助空間
原始數列: [51] 33 62 17 28 51'
第一次: [51]
第二次: [51] [33]
第三次: [51 62] [33]
第四次: [51 62] [17 33]
第五次: [51 62] [17 28 33]
第六次: [51 51' 62] [17 28 33]
first指針指向17,final指針指向62
4.希爾排序(又稱縮小增量法)
【基本思想】設置增量d1(<n),將全部n個記錄分成d1組,把所有相隔d1的記錄放在一個組中,即[k],[k+d],[k+2d]...在一組,在組內進行直接插入排序,依次取每組第i個記錄得到的序列爲一趟希爾排序的結果;設置新的增量d2<d1,重複分組排序,直到增量di減少到1。【跳躍式分堆兒排序】
【注】增量序列取法:①沒有除1之外的公因子;②增量遞減,最後一個增量值必須爲1。
原始數列:49 38 65 97 76 13 27 49' 55 04
d=5 分組:[49 13] [38 27] [65 49'] [97 55] [76 04]
組內排序:[13 49] [27 38] [49' 65] [55 97] [04 76]
第一趟希爾排序結果:13 27 49’ 55 04 49 38 65 97 76
d=3 分組:[ 13 55 38 76] [ 27 04 65 ] [ 49' 49 97]
第二趟希爾排序的結果:13 04 49' 38 27 49 55 65 97 76
d=1 ,共一大組,組內排序
第三趟希爾排序的結果:04 13 27 38 49’49 55 65 76 97
(二)交換排序
1.冒泡排序
【基本思想】給定一組數列,相鄰兩數相比較,逆序則交換。【兩兩比較,小者上浮,大者下沉】
最多經過n-1次冒泡可將n個數據全部排序
最好情況,初始序列有序,比較n-1次,移動0
最壞情況,初始序列倒序,比較n(n-1)/2,移動3n(n-1)/2
原始數列: [51] 33 62 17 28 51'
51>33,交換;51<62,不變;62>17,交換;62>28,交換;62>51',交換
第一趟冒泡排序結果:33 51 17 28 51’ 62
依次類推
2.快速排序
【基本思想】選取一個基數(每組第一個數),大於基數的在一堆兒,小於基數的再另一堆兒,等於基數的和大於的分一堆兒;在每一個堆兒裏繼續選取基數重複分堆兒直到不能再分(堆兒裏只有一個記錄)
最好情況,每次劃分得到的子序列長度大致相等,C(n)≤O(n*lbn).
最壞情況,每次劃分得到一個(n-1)的堆兒和一個空堆兒,即初始數列有序,
快排平均時間複雜度O(nlbn),最差爲O(n^2);平均空間複雜度S(n)=O(lbn);
原始數列:[51] 33 62 17 28 51'
第一趟後:[28 33 17 ] 51 [ 51' 62] //??28在第一個??
第二趟後:[17] 28 [33] 51 51' [62]
結束
(三)選擇排序
1.簡單選擇排序
【基本思想】分爲有序區和無序區,從無序區選取最小的一個記錄放在有序區的最小位置(兩個記錄交換),重複。
這個有點像直接插入排序,不同的是簡單選擇排序是依次在無序區的記錄中比較,而直接插入排序是在有序區中比較。
最好情況,移動次數0
最差情況,移動次數3(n-1)
平均時間複雜度O(n^2)
原始數列:51 33 62 17 28 51'
第一趟:[17] 33 62 51 28 51’ (51和17交換位置)
第二趟:[17 28] 62 51 33 51'
第三趟:[17 28 33] 51 62 51'
第四趟:[17 28 33 51] 62 51'
第五趟:[17 28 33 51 51'] 62
第六趟:[17 28 33 51 51' 62]
2.樹形選擇排序
【基本思想】首先對n個記錄的關鍵字進行兩兩比較,選取n/2個較小者;然後這n/2個較小者進行兩兩比較....如此重複,知道只剩1個關鍵字爲止。
每選擇一個記錄需要將進行[lbn]次比較,時間複雜度爲O(nlbn)
缺點:需要較多的輔助空間,與最大值進行多次多餘的比較
原始數列:51 33 62 17 28 51'
一趟樹形選擇排序過程:(從下往上依次兩兩比較,選取較小的記錄,直至選擇出最小的一個)
17
17 28
33 17 28
51 33 62 17 28 51’
3.堆排序
【堆的性質】
1.堆是一棵採用順序存儲結構的完全二叉樹
2.堆的根節點是關鍵字序列中的最小(或最大)值,分別稱爲小(或大)根堆
3.從根節點到每一個葉子節點路徑上的元素組成的序列都是按照元素值非遞減(非遞增)的
4.堆中的任意子樹也是堆
(四)歸併排序
【基本思想】將數列分成n個組,每個組一個元素(即每個組都是有序的),兩組之間兩兩合併,組內排序使之有序,重複至只有一個組。【有點像快排反着來的,en也不是很確切】
具有n個待排記錄的歸併次數爲lbn,一趟歸併的時間複雜度爲O(n),整個歸併(無論最好最壞情況)時間複雜度爲O(nlbn),空間複雜度O(n)。
原始數列:[51] [33] [62] [17] [28] [51']
一趟歸併:[33 51] [17 62] [28 51']
兩趟歸併:[17 33 51 62 ] [28 51']
三趟歸併:[17 28 33 51 51' 62]
(五)基數排序(不需要進行關鍵字比較和記錄移動)
1.多關鍵字排序
2.鏈式基數排序
排序方法 | 平均時間複雜度 | 最壞情況 | 輔助空間 | 穩定性 |
直接插入排序 | O(n^2) | O(n^2) | O(1) | 穩定 |
冒泡排序 | O(n^2) | O(n^2) | O(1) | 穩定 |
直接選擇排序 | O(n^2) | O(n^2) | O(1) | 穩定 |
希爾排序 | O(n^1.3) | O(n^1.3) | O(1) | 不穩定 |
快速排序 | O(nlbn) | O(n^2) | O(lbn) | 不穩定 |
堆排序 | O(nlbn) | O(nlbn) | O(1) | 不穩定 |
歸併排序 | O(nlbn) | O(nlbn) | O(n) | 穩定 |
基數排序 | O(d*(rd+n)) | O(d*(rd+n)) | O(rd) | 穩定 |