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二路插入排序 ...