按照題目描述,我們需要將插入排序中的5~7行,while迴圈實現的將「比a[i]大的數後移」的功能用二分查詢的思路進行優化。2.3-5也有提到優化思路,即插入排序每一次迴圈結束後前面的i個數已經完成從小到大的排序,只需要將目標值a[j]與前i個數的中間值a[i/2]比較,就能知道a[j]應該在的區間,並減少一半的判斷時間。
偽**://_(:зゝ∠)_
binary_insertion_sort ( a , l , r )//輸入a[0..n],0,n
if r > 2……………………………………………………c1
binary_insertion_sort ( a , l , r-1 )…………c2//r==2之前一直呼叫函式對前面的r-1個元素進行排序
key = a[ r ]………………………………………………c3//待插入的值給key
binary_insert ( a , l , r - 1 , key )………………c4//將a[ r ]插入前面已經排好的0~r-1序列中
//遞迴的插入排序主函式
binary_insert ( a , l , r , key )
if l > r……………………………………………………c5
a[ l] = key…………………………………………c6
return………………………………………………c7//若左溢位則將key賦給溢位之前的位置,若右溢位則賦值給l=r+1這個溢位位,即未排序的那個數的位置不動
else if key <= a[ ( l + r ) / 2]…………………………c8//若key值在二分點左側則要將二分點右側所有元素右移一位
for i = r downto ( l + r ) / 2……………………c9
a[ i + 1 ] = a [ i ]……………………………………c10
binary_insert ( a , l , ( l + r ) / 2 , key )……c11//繼續找key該呆的位置
else binary_insert ( a , ( l + r ) / 2 , r , key )…………c12//若key值在二分點右側則不做處理,繼續迭代
//二分比較並移動較大項函式
鑑於計算過程太繁雜,手碼的話要浪費大量時間,就直接給結果了_(:зゝ∠)_,其中k1~5都是用於替換c1~11組成的一次算式的常數。
binary_insertion_sort函式的遞迴式為:
t1( n ) = k4 + t1( n - 1 ) + t2( n ),n>=2.
binary_insert函式的遞迴式為:
t2 ( n ) = k1 * n + k2 + t2 ( n - 1 ),n>1
t2 ( 1 ) = k3, n=1.
通式:(lg(n)代表以2為底,n的對數,書上有說明
t2( n ) = 2 * k1 * n + k2 * lg(n) - 2 * k1 +k3
t1( n ) = k1 * (n² + n - 2) + k2 * lg(n!) + k5 * ( n - 1 )//用斯特林公式將n!做近似處理,不懂的這裡
t1( n ) = k1 * n² + k2 * n *lg(n) + ( k1 - lg(e) *k2 + k5 ) *n +lg((2*π*n)½) -2 * k1 - k5
故將while替換後也不會對原插入排序的複雜度o(n²)造成多大影響,更不可能達到題目要求的o(n*lgn)。
但是這做法也做了對while的部分優化,優化了多少呢?有興趣的同學請看下面。
將k1~k5的值代入原式(自己拿草稿紙寫一下吧
k1= 0.5 * ( c9 + c10 + c11 )
k2= c5 + c8 + c9
k3= c5 + c6 + c7
k4= c1 + c2 + c3 + c4
k5= - k2 + k3 + k4
接下來將這篇裡的k1、k2的值也代入原式t(n)。(用書裡第14~15頁的**與t(n)的通式比較也行。
對比兩組**中的相似部分,本文中n²的係數k1中包含了c10(自減)、c11(換位)、c12(呼叫自己),而書中n²的係數包含了c5(比較大小、判斷是否溢位)、c6(換位)、c7(自減)。可見其中 自減 和 換位 兩項沒有被優化,而本文中的比較大小和判斷是否溢位分別是c8(比較大小)、c5(判斷是否溢位),他們分別屬於,c8->(k2,k5),c5->(k2,k3,k5)。如果我們忽略小值,那麼c8(比較大小)的時間複雜度為o(n*lgn),c5(判斷是否溢位)的時間複雜度為o(n)。
如果把比較大小和判斷是否溢位這兩個判斷語句拆開來算,那麼這個改動對原插入排序排序演算法的的優化點為,將「比較兩數大小」由o(n²)降低到o(n*lgn),將「判斷是否溢位」o(n²)降低到o(n),額外增添了「自己呼叫自己」複雜度為o(n²)。
全域性優化為o(n²)-o(n*lgn)-o(n)。不知道「自己呼叫自己」這步的具體時長與另外兩步有多大區別,好心前輩可以幫忙補充一下或指出我的錯誤,不然看起來好像還不如不優化_(:зゝ∠)_,謝謝大家,喜歡請點贊(>^ω^<)。
關於堆排序 參考自演算法導論
堆排序是一種很有用的排序演算法,有用的並不是在排序上的用處,而是那個大根堆和小根堆的建立,在平時的運用中,舉足輕重!乙個最有用的例項就是作業系統的程序的最大優先權排程演算法。從很多程序中,找到優先順序最大的程序,然後分配cpu資源。堆排序的主要步驟也就是建立堆。一旦最大堆 最小堆 建立好了,排序也是...
演算法導論 隨機演算法
一.概率分布 對於有些問題本身是屬於概率問題,如僱傭問題 對於此類問題,我們需要利用概率分析來得到演算法的執行時間,有時也用來分析其他的量。例如,僱傭問題中的費用問題也需要結合概率分析來計算得到。為了使用概率分析,我們必須使用或者假設已知關於輸入的概率分布,然後通過分析該演算法計算出平均情況下的執行...
《演算法導論》 演算法導論2 2 1插入排序
2.1 插入排序。我們分析的第乙個演算法是插入排序演算法,輸入 n個數 a1,a2,a3,a4,a5,a6,a7 an 輸出 序列的乙個排列 即重新排序 a1 a2 a3 使a1 a2 a3 插入排序演算法的偽 是以乙個過程的形式給出的,稱為insertion sort,它的引數是乙個陣列。包括了n...