1. 程式人生 > >完全二叉樹和堆排序

完全二叉樹和堆排序

堆排序演算法複雜度雖然也是O(nlgn),但其常數因子較大,而且在實際測試中發現和快速排序、二路歸併排序相比速度會慢不少,但堆有其獨特的優勢:

(1) 堆排序僅需要O(1)的空間,這是其他O(nlgn) 排序演算法所沒有的特點;

(2) 堆結構可以以O(1) 的代價取出最大值(最小值),這在優先順序佇列中得到廣泛應用,這些應用不需要完全排序,只需要“快速取出最值”,堆結構在插入、刪除、修改時的複雜度均為O(lgn),比直接使用連結串列要好(插入的複雜度為O(n))

堆排序中使用的結構就是完全二叉樹,以下證明若干完全二叉樹的性質。

結點高度:定義成從此結點到葉子結點的最長路徑;可以證明,某結點的最左路徑,必是最長路徑,即如果結點序號為i,則i, i*2, i*2^2,....,i*2^h為其最長路徑。

 完全二叉樹高度:       定義成完全二叉樹根結點的高度,也是結點高度的最大值;

1. 證明完全二叉樹高度為[log n] (下取整函式)

 假設 n = 2^h + r,其中h>=0, 0<=r<2^h,則由完全二叉樹的定義可知,此樹的高度為h,而[log n]=[log(2^h + r)]正好等於h,故命題得證

2. 建堆的複雜度為O(n)

演算法導論中有詳細的證明,需要使用如下數學命題,數列{an},其中an = nx^n,當|x|<1時,其和 S = x / (1-x)^2

 以下使用等比數列簡要證明 

求S(n) = 1 * x + 2 * x^2 + ... + n * x^n,設G(n) = x + x^2 +x^3 +...+ x^n

=> S(n) – G(n) = x^2 + 2 * x^3 +...+(n-1) * x^n

=> (S(n) – G(n)) / x = x + 2 * x^2 +...+ (n-1) * x^(n-1)

=> (S(n) – G(n)) / x = S(n) – n * x^n

=>  S(n) = (G(n) – n * x^(n+1)) / (1-x)

當|x|<1,n 趨向於無窮大時,G(n) 趨向於x / (1-x),n * x^(n+1)趨向於0,故S = x / (1-x)^2

3. 最壞情況下,插入建堆的複雜度為O(nlgn)

 對於大頂堆,最壞情況為升序排列的數列,除第一個元素外,每個元素都要作交換操作且交換到根結點,序號為i的元素,需要[lgi]次操作,因此對於n個元素,插入建堆的時間為S(n) =   [lg1] + [lg2] + [lg3] +...+ [lgn]

S(n) < lg1 + lg2 + lg3 +...+ lgn =lg(n!) 根據stirling 公式,S(n) = O(nlgn)

 S(n) > lg1/2 + lg2/2 + lg3/2 + ... +lgn/2 = lg(n!) – lg2^n = nlgn – n,即S(n) = Ω(nlgn),命題得證

注意插入建堆和原有的建堆方式結果有可能不一樣,對於大頂堆來講,1、2、3就是一個反例