1. 程式人生 > >常用的排序算法的時間復雜度和空間復雜度

常用的排序算法的時間復雜度和空間復雜度

排好序 dsm 特性 樹形選擇排序 臨時 快速排序 向上 [88 規律

常用的排序算法的時間復雜度和空間復雜度

排序法

最差時間分析 平均時間復雜度 穩定度 空間復雜度
冒泡排序 O(n2) O(n2) 穩定 O(1)
快速排序 O(n2) O(n*log2n) 不穩定 O(log2n)~O(n)
選擇排序 O(n2) O(n2) 穩定 O(1)
二叉樹排序 O(n2) O(n*log2n) 不一頂 O(n)

插入排序

O(n2) O(n2) 穩定 O(1)
堆排序 O(n*log2
n)
O(n*log2n) 不穩定 O(1)
希爾排序 O O 不穩定 O(1)

1、時間復雜度
(1)時間頻度 一個算法執行所耗費的時間,從理論上是不能算出來的,必須上機運行測試才能知道。但我們不可能也沒有必要對每個算法都上機測試,只需知道哪個算法花費的時間多,哪個算法花費的時間少就可以了。並且一個算法花費的時間與算法中語句的執行次數成正比例,哪個算法中語句執行次數多,它花費時間就多。一個算法中的語句執行次數稱為語句頻度或時間頻度。記為T(n)。
(2)時間復雜度 在剛才提到的時間頻度中,n稱為問題的規模,當n不斷變化時,時間頻度T(n)也會不斷變化。但有時我們想知道它變化時呈現什麽規律。為此,我們引入時間復雜度概念。 一般情況下,算法中基本操作重復執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函數。記作T(n)=O(f(n)),稱O(f(n)) 為算法的漸進時間復雜度,簡稱時間復雜度。

在各種不同算法中,若算法中語句執行次數為一個常數,則時間復雜度為O(1),另外,在時間頻度不相同時,時間復雜度有可能相同,如T(n)=n2+3n+4與T(n)=4n2+2n+1它們的頻度不同,但時間復雜度相同,都為O(n2)。 按數量級遞增排列,常見的時間復雜度有:常數階O(1),對數階O(log2n),線性階O(n), 線性對數階O(nlog2n),平方階O(n2),立方階O(n3),..., k次方階O(nk),指數階O(2n)。隨著問題規模n的不斷增大,上述時間復雜度不斷增大,算法的執行效率越低。 2、空間復雜度 與時間復雜度類似,空間復雜度是指算法在計算機內執行時所需存儲空間的度量。記作: S(n)=O(f(n)) 我們一般所討論的是除正常占用內存開銷外的輔助存儲單元規模。討論方法與時間復雜度類似,不再贅述。
(3)漸進時間復雜度評價算法時間性能   主要用算法時間復雜度的數量級(即算法的漸近時間復雜度)評價一個算法的時間性能。

2、類似於時間復雜度的討論,一個算法的空間復雜度(Space Complexity)S(n)定義為該算法所耗費的存儲空間,它也是問題規模n的函數。漸近空間復雜度也常常簡稱為空間復雜度。
空間復雜度(Space Complexity)是對一個算法在運行過程中臨時占用存儲空間大小的量度。一個算法在計算機存儲器上所占用的存儲空間,包括存儲算法本身所占用的存儲空間,算法的輸入輸出數據所占用的存儲空間和算法在運行過程中臨時占用的存儲空間這三個方面。算法的輸入輸出數據所占用的存儲空間是由要解決的問題決定的,是通過參數表由調用函數傳遞而來的,它不隨本算法的不同而改變。存儲算法本身所占用的存儲空間與算法書寫的長短成正比,要壓縮這方面的存儲空間,就必須編寫出較短的算法。算法在運行過程中臨時占用的存儲空間隨算法的不同而異,有的算法只需要占用少量的臨時工作單元,而且不隨問題規模的大小而改變,我們稱這種算法是“就地/"進行的,是節省存儲的算法,如這一節介紹過的幾個算法都是如此;有的算法需要占用的臨時工作單元數與解決問題的規模n有關,它隨著n的增大而增大,當n較大時,將占用較多的存儲單元,例如將在第九章介紹的快速排序和歸並排序算法就屬於這種情況。

當一個算法的空間復雜度為一個常量,即不隨被處理數據量n的大小而改變時,可表示為O(1);當一個算法的空間復雜度與以2為底的n的對數成正比時,可表示為0(10g2n);當一個算法的空I司復雜度與n成線性比例關系時,可表示為0(n).若形參為數組,則只需要為它分配一個存儲由實參傳送來的一個地址指針的空間,即一個機器字長空間;若形參為引用方式,則也只需要為其分配存儲一個地址的空間,用它來存儲對應實參變量的地址,以便由系統自動引用實參變量。

常用的內部排序方法有:交換排序(冒泡排序、快速排序)、選擇排序(簡單選擇排序、堆排序)、插入排序(直接插入排序、希爾排序)、歸並排序、基數排序(一關鍵字、多關鍵字)。

一、冒泡排序:

1.基本思想:

兩兩比較待排序數據元素的大小,發現兩個數據元素的次序相反時即進行交換,直到沒有反序的數據元素為止。

2.排序過程:

設想被排序的數組R[1..N]垂直豎立,將每個數據元素看作有重量的氣泡,根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數組R,凡掃描到違反本原則的輕氣泡,就使其向上"漂浮",如此反復進行,直至最後任何兩個氣泡都是輕者在上,重者在下為止。

【示例】:

49 13 13 13 13 13 13 13

38 49 27 27 27 27 27 27

65 38 49 38 38 38 38 38

97 65 38 49 49 49 49 49

76 97 65 49 49 49 49 49

13 76 97 65 65 65 65 65

27 27 76 97 76 76 76 76

49 49 49 76 97 97 97 97

二、快速排序(Quick Sort)

1.基本思想:

在 當前無序區R[1..H]中任取一個數據元素作為比較的"基準"(不妨記為X),用此基準將當前無序區劃分為左右兩個較小的無序區:R[1..I-1]和 R[I+1..H],且左邊的無序子區中數據元素均小於等於基準元素,右邊的無序子區中數據元素均大於等於基準元素,而基準X則位於最終排序的位置上,即 R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H),當R[1..I-1]和R[I+1..H]均非空時,分別對它們進行上述的劃分過 程,直至所有無序子區中的數據元素均已排序為止。

2.排序過程:

【示例】:

初始關鍵字 [49 38 65 97 76 13 27 49]

第一次交換後 [27 38 65 97 76 13 49 49]

第二次交換後 [27 38 49 97 76 13 65 49]

J向左掃描,位置不變,第三次交換後 [27 38 13 97 76 49 65 49]

I向右掃描,位置不變,第四次交換後 [27 38 13 49 76 97 65 49]

J向左掃描 [27 38 13 49 76 97 65 49]

(一次劃分過程)

初始關鍵字 [49 38 65 97 76 13 27 49]

一趟排序之後 [27 38 13] 49 [76 97 65 49]

二趟排序之後 [13] 27 [38] 49 [49 65]76 [97]

三趟排序之後 13 27 38 49 49 [65]76 97

最後的排序結果 13 27 38 49 49 65 76 97

三、簡單選擇排序

1.基本思想:

每一趟從待排序的數據元素中選出最小(或最大)的一個元素,順序放在已排好序的數列的最後,直到全部待排序的數據元素排完。

2.排序過程:

【示例】:

初始關鍵字 [49 38 65 97 76 13 27 49]

第一趟排序後 13 [38 65 97 76 49 27 49]

第二趟排序後 13 27 [65 97 76 49 38 49]

第三趟排序後 13 27 38 [97 76 49 65 49]

第四趟排序後 13 27 38 49 [49 97 65 76]

第五趟排序後 13 27 38 49 49 [97 97 76]

第六趟排序後 13 27 38 49 49 76 [76 97]

第七趟排序後 13 27 38 49 49 76 76 [ 97]

最後排序結果 13 27 38 49 49 76 76 97

四、堆排序(Heap Sort)

1.基本思想:

堆排序是一樹形選擇排序,在排序過程中,將R[1..N]看成是一顆完全二叉樹的順序存儲結構,利用完全二叉樹中雙親結點和孩子結點之間的內在關系來選擇最小的元素。

2.堆的定義: N個元素的序列K1,K2,K3,...,Kn.稱為堆,當且僅當該序列滿足特性:

Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2])

堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉子結點的關鍵字均大於等於其孩子結點的關鍵字。例如序列10,15,56,25,30,70就是一個 堆,它對應的完全二叉樹如上圖所示。這種堆中根結點(稱為堆頂)的關鍵字最小,我們把它稱為小根堆。反之,若完全二叉樹中任一非葉子結點的關鍵字均大於等 於其孩子的關鍵字,則稱之為大根堆。

3.排序過程:

堆排序正是利用小根堆(或大根堆)來選取當前無序區中關鍵字小(或最大)的記錄實現排序的。我們不妨利用大根堆來排序。每一趟排序的基本操作是:將當前無 序區調整為一個大根堆,選取關鍵字最大的堆頂記錄,將它和無序區中的最後一個記錄交換。這樣,正好和直接選擇排序相反,有序區是在原記錄區的尾部形成並逐 步向前擴大到整個記錄區。

【示例】:對關鍵字序列42,13,91,23,24,16,05,88建堆

五、直接插入排序(Insertion Sort)

1. 基本思想:

每次將一個待排序的數據元素,插入到前面已經排好序的數列中的適當位置,使數列依然有序;直到待排序數據元素全部插入完為止。

2. 排序過程:

【示例】:

[初始關鍵字] [49] 38 65 97 76 13 27 49

J=2(38) [38 49] 65 97 76 13 27 49

J=3(65) [38 49 65] 97 76 13 27 49

J=4(97) [38 49 65 97] 76 13 27 49

J=5(76) [38 49 65 76 97] 13 27 49

J=6(13) [13 38 49 65 76 97] 27 49

J=7(27) [13 27 38 49 65 76 97] 49

J=8(49) [13 27 38 49 49 65 76 97]

六、希爾排序

1.排序思想:

先 取一個小於n的證書d1作為第一個增量,把文件的全部記錄分成d1組。所有距離為d1的倍數的記錄放在同一組中。先在各組內進行直接插入排序,然後取第二 個增量d2<d1重復上述的分組和排序,直到所取的增量dt=1,即所有記錄放在同一組中進行直接插入排序為止。該方法實際上是一種分組插入方法。

2.排序過程:

[初始關鍵字] 72 28 51 17 96 62 87 33 45 24

d1=n/2=5 62 28 33 17 24 72 87 51 45 96

d2=d1/2=3 17 24 33 62 28 45 87 51 72 96

d3=d2/2=1 17 24 28 33 45 51 62 72 87 96

七、歸並排序

1.排序思想:

設兩個有序的子文件(相當於輸入堆)放在同一向量中相鄰的位置上:R[low..m],R[m+1..high],先將它們合並到一個局部的暫存向量R1(相當於輸出堆)中,待合並完成後將R1復制回R[low..high]中。

2.排序過程:

【示例】:

初始關鍵字 [46][38][56][30][88][80][38]

第一趟歸並後[38 46][30 56][80 88][38]

第二趟歸並後[30 38 46 56][38 80 88]

最終歸並結果[30 38 38 46 56 80 88]

八、基數排序

1.排序思想:

(1)根據數據項個位上的值,把所有的數據項分為10組;

(2)然後對這10組數據重新排列:把所有以0結尾的數據排在最前面,然後是結尾是1的數據項,照此順序直到以9結尾的數據,這個步驟稱為第一趟子排序;

(3)在第二趟子排序中,再次把所有的數據項分為10組,但是這一次是根據數據項十位上的值來分組的。這次分組不能改變先前的排序順序。也就是說,第二趟排序之後,從每一組數據項的內部來看,數據項的順序保持不變;

(4)然後再把10組數據項重新合並,排在最前面的是十位上為0的數據項,然後是10位為1的數據項,如此排序直到十位上為9的數據項。

(5)對剩余位重復這個過程,如果某些數據項的位數少於其他數據項,那麽認為它們的高位為0。

2.排序過程

【示例】

初始關鍵字 421 240 035 532 305 430 124

第一趟排序後[240 430] [421] [532] [124] [035 305]

第二趟排序後(305) (421 124) (430 532 035) (240)

最後排序結果(035) (124) (240) (305) (421 430) (532)

常用的排序算法的時間復雜度和空間復雜度