各類排序方法小結

2021-06-21 16:08:46 字數 3479 閱讀 3870

1. 插入排序

a) 直接插入排序

從0開始構建乙個有序序列,把無序序列中的數字一一插入有序數列中(可以共用乙個陣列)。插入的時候,就是從頭比較。

平均:o(n²)

最壞:o(n²)

空間:o(1)

b) 折半插入排序

就是在直接插入排序基礎上,插入有序序列的時候採用了折半查詢。

時間複雜度上,僅僅減少了比較(查詢)的次數,但記錄移動次數不變,時間複雜度和空間複雜度均同a)

c) 2-路插入排序

很2的一種排序,本質上還是和折半插入排序一樣;只不過選取無序數列的第乙個數,以此為標準分為兩個有序數列,然後插入的時候就可以減少一半的移動次數(查詢仍然可以按照折半插入排序來,實現起來,應該就是分成兩個序列後,對每乙個插入的數字,選擇乙個有序序列呼叫b)

這個排序多了乙個序列的空間;時間減少一半;記錄移動次數約為n

²/8. 

但是複雜度仍然是

o(n²)

d) 表插入排序

表插入排序適合靜態鍊錶的儲存結構適合的排序(靜態鍊錶:陣列+

鍊錶)。基本的思想也是插入,插入的方式其實就是修改指標,不需要記錄移動。但是排序完成後,由於是鍊錶結構,沒辦法隨機查詢,如果要隨機查詢,需要再把這些鍊錶重新按照其陣列下標大小進行排序。用到了時候再詳細使用吧。

時間複雜度還是o(n²)

e) 希爾排序

又稱為縮小增量排序。按照一定的增量k

,把原序列劃分為

k個子序列,對這

k個子序列分別進行插入排序,稱為一趟排序。然後

k減小一些,再進行一趟排序,直到

k=1這一趟排序完成後,排序完成。

時間複雜度大概是o(n**1.3~n**1.5)

這樣。取決於增量

k的序列。

2. 交換排序

a) 氣泡排序

冒泡法就不說了,很簡單。沒什麼注意的,除了和簡單選擇排序區分一下。時間複雜度o(n**2)。

b) 快速排序

基本思想:選擇數列中的乙個pivotkey

,將數列分為兩個子數列,大於

pivotkey

和小於pivotkey

。然後對每個子串行分別進行快速排序。

分成兩個子串行的方法很有意思:從序列兩端的指標向中間移動:下標low

增加,high

減少;如果

low指向的

key大於

pivotkey

,將該值換到

high

上面,high

開始減少。反正亦然;直到

low == high

,這時候

low和

high

所指位置即為

pivotkey

位置。

平均時間複雜度:o(k n ln(n)),k

是乙個常數;是目前所有內部排序中最快的方法。

最壞時間複雜度:o(n²) 

同氣泡排序,可以按照「三者取中」法則來選取

pivotkey

,從而改善最壞情況的效能。

3. 選擇排序

a) 簡單選擇排序

打擂台排序,我不動腦子就寫出來的那個排序。

b) 樹形選擇排序

仍然是打擂台排序,但是這次不僅要第一名,而且要第二名第三名的打擂台了,所以用一種二叉樹結構來進行比較。每一次比較都可以選出乙個最小的,然後把選出的位置換成無窮大,再次比賽,出來次小的,以此類推,最後排序。時間複雜度o(n log n)

,但是缺點是所需要的空間很多。

c) 堆排序

乙個時間複雜度為o(n log n)

,空間複雜度為

o(1)

的排序,本質上是樹形排序的改進,按照堆的定義構成乙個完全二叉樹,然後從堆頂端輸出最小值

/最大值,再把堆的最後乙個替換到堆的第乙個後進行調整。整個排序演算法主要完成兩個步驟:

1. 建乙個堆;

2. 調整堆頂元素重新構成乙個堆。具體方法在此不相信敘述。

4. 歸併排序

遞迴的把兩個有序序列合併到乙個序列。時間複雜度o(n log n). 

是一種穩定的排序。

5. 基數排序radix sorting

a) 多關鍵字排序

這個不是要**的問題,而是只當乙個序列有多個關鍵字時候,排序的方式,包括msd

,lsd

。典型的例子是撲克牌排序,按照花色和面值兩個關鍵字排序,可以有

msd好

lsd兩種不同的方式。這裡我們假設花色是主關鍵字的話,則

msd即先按照花色分成四堆牌,然後再在每一堆牌裡面按照面值排序,最後四堆牌合起來;

lsd則是先按照面值分成

13堆牌,合起來,然後再按照花色進行穩定的排序(即想等的值,原來在前面的還是在前面),這樣也可以排好。

b) 鏈式基數排序

鏈式基數排序借助多關鍵字排序的思想,首先把單個關鍵字分割成多個關鍵字(比如,關鍵字是0-999

的數值,可以分成百位數,十位數,個位數三個關鍵字),然後按照

lsd方式對這些關鍵字重新排序,這樣只需要三趟排序就可以完成。用鍊錶的方式來排序最省空間,所以稱為鏈式基數排序。對於

n個記錄,記錄含有

d個關鍵字且關鍵字取值範圍是

rd個值(比如上面例子,

d = 3 , rd = 10

),則其時間複雜度為

o(d(n + rd))

,即每一趟分配時間為

n, 收集時間為

rd, 

共需進行

d趟。需要

rd個表頭和表尾來作為輔助儲存空間。

6. 排序總結:

基於上述排序方法,可以分成以下幾類排序:

a) 簡單排序:包括直接插入(

改進:折半插入,

2-路插入

),氣泡排序,簡單選擇

b) 快速排序(基於氣泡排序)

c) 歸併排序(基於歸併兩個有序陣列)

d) 堆排序(基於樹形選擇排序)

e) 基數排序(基於多關鍵字排序)

f) 希爾排序(基於插入排序)

其中簡單排序時間複雜度均為o(n

²), 

三個高階排序,快速,歸併,堆均為

o(n log n)

,基數排序為

o(d ( n + rd))

,希爾排序是

o(n**1.3~n**1.5). 

空間複雜度各異。

還要注意的乙個問題是,如果待排序的每乙個記錄很大,交換移動需要花費大量時間,則可以考慮使用表排序方式來減少移動次數。大致的思路是,建立乙個靜態鍊錶,先用選擇的排序方法在將指標排好序(鍊錶排序),再用乙個方法,通過有序的指標來對記錄排序,從而達到記錄有序。

各類小問題小結

問題1 命令列執行cd命令能夠順利進入檔案目錄下,但在shell指令碼下報錯找不到檔案目錄。原因 linux和windows下回車換行不同,檔案中某些字元格式解釋不一致。解決辦法 進入檔案中 vim sh 檢視檔案格式 set ff 修改檔案格式 set ff unix 修改為多格式均可 set f...

各類排序演算法

快速排序 void quicksort int data,int low,int high if a k a i 冒泡法 void maopao int a,int num num元素個數 歸併排序 插入排序 include stdafx.h includeusing namespace std d...

各類排序演算法比較

排序演算法 重點時間複雜度 穩定性直接插入排序 將待插入元素插入到已有序序列中的某個合適位置,得到新有序序列 最壞情況下o n n y折半插入排序 在決定當前元素插入位置時不採用插入查詢的方式,而是二分查詢 相比直接插入,比較的次數明顯減半,但移動的次數沒有減少。所以還是o n n y二路插入排序 ...