第五課主要引出了兩個非常有趣的排序演算法——它們的時間複雜度竟然是θ(n),也就是說時間複雜度是線性的。
首先來看看之前提到過的幾個排序演算法:
quicksort ——θ(nlgn)
heapsort——θ(nlgn)
merge sort——θ(nlgn)
insert sort——n^2
所有這些排序演算法,能否比nlgn更快?
不能,因為他們都採用了同樣的乙個模型,比較演算法模型。也就是在排序的時候都會取兩個數進行比較,這樣的演算法的侷限性導致不可能超過nlgn的時間複雜度,我們可以用決策樹的模型來證明:
例:決策樹 a1 a2 a3
大於 1比2 小於
2比3 1比3
123 1比3 213 2比3
132 312 231 321
通過每一次的對比,決策樹分出了兩個分支,現在要對n個元素進行排序,ai,aj i,j在1~n的範圍內
構造這樣乙個決策樹,左邊 ai≤aj,右邊是ai>aj,每乙個葉子節點都是一種排序的可能結果,一共有n!個結果
這個決策樹的高度,也就是最長的路徑,樹的深度就是需要求的時間尺度。
證明:一共是有n!個葉子節點,假設這個樹的高度是h,那麼高度是h的數二分節點最多是2^h
n!≤2^h
lgn!≤h
利用斯特林公式,n!近似等於(n/e)^n
h≥nlg(n/e)=nlgn-nlge
所以h=ω(nlgn)
得證!還有一些排序演算法不能用簡單的決策樹來表示,突破決策樹方法的關鍵是我們意識到,我們其實在使用比較排序模型的時候假設了對於乙個n數列來說,只有一棵樹。這才導致了這個模型是有極限的。下面來介紹兩個排序演算法
1.計數排序
寫出計數排序的偽**:
a= a是待排序數列,a裡的值取值範圍在1~k的整數
b[i] 是a排序的結果數列
c[i] 是輔助序列 c的長度是k,用來記錄a中各個整數出現的次數
for i<- 1 to k
do c[i]<-0
for j<-1 to n
do c[a[j] <- c[a[j] +1
初始化for i<- 2 to k
do c[i]<-c[i]+c[i-1]
分配for j<- n downto 1
do b[c[a[j]] <- a[j]
c[a[j]<- c[a[j]-1
結果從偽**來看,是不是暈了???
例子:排序a= 4,1,3,4,3
c=0000然後變成1022記錄了每乙個數字出現的次數,然後將c的每項都遞迴的加起來,得到c=1135
然後來得出結果
j=5時 b[3]=a[5]=3 然後 c[3]減1
j=4時 b[5]=a[4]=4 然後 c[4]減1
……這樣就通過輔助數列把a排列成了b
我們來計算一下這個演算法的複雜度
t(n)=θ(n+k)
乙個線性時間複雜度的演算法就產生了。最終的時間其實還和k相關,k如果較大的話還不如快速排序
我們這裡提到的演算法都是穩定排序演算法:穩定排序演算法是指保證了相等元素的相對位置穩定不變
再來看第二個演算法
2.基數排序演算法
在排序的時候對末位開始排序,然後再對第二位開始排序
例子:對329 457 657 839 436 720 355進行排序
先排末位得到:720 355 436 457 657 329 839
再排第二位得到:720 355 436 457 657 329 839
最後再排首位得到結果
那麼在每一輪的排序中,我們都可以使用計數排序演算法。
在計算機假設有n個整數在0~2^b-1範圍內,也就是說每個數的的b位二進位制數,我們對他們進行排序
可以把整數拆分成b/r個段,每個段長度都有r
b/r是一共要比較的輪數,k=2^r
t(n)=b/r * (n+k)=b/r * (n+2^r)
那麼我們可以選取恰當的r來得到最好的t(n),r=lgn的時候得到最好的結果
t(n)=o(b*n/lgn)
若b=n^d
那麼t(n)=θ(dn)這個演算法也是線性尺度的排序演算法。
第五課 其它型別排序演算法
tags categories 第二節 計數排序 第三節 桶排序 第四節 基數排序 希爾排序是之前插入排序的變形。希爾排序 shell sort 是 種分組插入排序演算法。首先取乙個整數d n 2,將元素分為d個組,每組相鄰量元素之間距離為d,在各組內進行直接插入排序 取第二個整數d2 d 2,重複...
演算法導論 基數排序
時間複雜度 o n 基本思路 兩個數比較大小,我們的直觀感覺是先比較高位,若相同則比較低位。但是這樣做需要記錄額外的資料,浪費空間。而基數排序則是先比較低位,再比較高位。通過各個位的比較進行排序,如果陣列元素最大有n位,則總共需要n次排序。注意 按位排序必須是穩定排序,所以在這我選擇了計數排序。具體...
排序演算法 五 基數排序
概念 時間複雜度最好 o n k k表示最大值的位數。最壞 o n k 平均 o n k 演示 399 298,98,1 的排序過程 1.先把資料變成相同位數的值 399298 098001 2.從個位數開始遍歷 001298 098399 3 十位數遍歷 001298 098399 4.百位數遍歷...