完全二叉树和堆排序

堆排序算法复杂度虽然也是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就是一个反例


你可能感兴趣的:(完全二叉树和堆排序)