(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的不斷增大,上述時間複雜度不斷增大,算法的執行效率越低。 二、空間複雜度 與時間複雜度相似,空間複雜度是指算法在計算機內執行時所需存儲空間的度量。記做: S(n)=O(f(n)) 咱們通常所討論的是除正常佔用內存開銷外的輔助存儲單元規模。討論方法與時間複雜度相似,再也不贅述。
(3)漸進時間複雜度評價算法時間性能 主要用算法時間複雜度的數量級(即算法的漸近時間複雜度)評價一個算法的時間性能。
二、相似於時間複雜度的討論,一個算法的空間複雜度(Space Complexity)S(n)定義爲該算法所耗費的存儲空間,它也是問題規模n的函數。漸近空間複雜度也經常簡稱爲空間複雜度。
空間複雜度(Space Complexity)是對一個算法在運行過程當中臨時佔用存儲空間大小的量度。一個算法在計算機存儲器上所佔用的存儲空間,包括存儲算法自己所佔用的存儲空間,算法的輸入輸出數據所佔用的存儲空間和算法在運行過程當中臨時佔用的存儲空間這三個方面。算法的輸入輸出數據所佔用的存儲空間是由要解決的問題決定的,是經過參數表由調用函數傳遞而來的,它不隨本算法的不一樣而改變。存儲算法自己所佔用的存儲空間與算法書寫的長短成正比,要壓縮這方面的存儲空間,就必須編寫出較短的算法。算法在運行過程當中臨時佔用的存儲空間隨算法的不一樣而異,有的算法只須要佔用少許的臨時工做單元,並且不隨問題規模的大小而改變,咱們稱這種算法是「就地/"進行的,是節省存儲的算法,如這一節介紹過的幾個算法都是如此;有的算法須要佔用的臨時工做單元數與解決問題的規模n有關,它隨着n的增大而增大,當n較大時,將佔用較多的存儲單元,例如將在第九章介紹的快速排序和歸併排序算法就屬於這種狀況。
如當一個算法的空間複雜度爲一個常量,即不隨被處理數據量n的大小而改變時,可表示爲O(1);當一個算法的空間複雜度與以2爲底的n的對數成正比時,可表示爲0(10g2n);當一個算法的空I司複雜度與n成線性比例關係時,可表示爲0(n).若形參爲數組,則只須要爲它分配一個存儲由實參傳送來的一個地址指針的空間,即一個機器字長空間;若形參爲引用方式,則也只須要爲其分配存儲一個地址的空間,用它來存儲對應實參變量的地址,以便由系統自動引用實參變量。
經常使用的內部排序方法有:交換排序(冒泡排序、快速排序)、選擇排序(簡單選擇排序、堆排序)、插入排序(直接插入排序、希爾排序)、歸併排序、基數排序(一關鍵字、多關鍵字)。
1、冒泡排序:
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
2、快速排序(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
3、簡單選擇排序
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
4、堆排序(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建堆
5、直接插入排序(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]
6、希爾排序
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
7、歸併排序
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]
8、基數排序
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)