您的位置:首页 > 其它

算法导论第六章6.3建堆和6.4堆排序算法课后答案

2014-01-02 19:14 1281 查看
6.3-2 在BUILD-MAX-HEAP的第2行代码中,为什么希望循环下标i从向下取整leghth[A]/2降到1,而

不是从1升到向下取整leghth[A]/2?

因为如果用递增循环从下标i=1开始,那么i的两个左右子树对于任意排序的数组来说就可能出现

左右子树不是最大堆的情况(使用MAX-HEAPIFY(A,i)函数必须满足左右子树是最大堆)。

    如果用递减循环从下标i=leghth[A]/2开始,那么根据6.1-7知i=leghth[A]/2的结点是刚开始

含有子结点的情况,这时,子结点所组成的树只含有1个结点,那么肯定满足最大堆的情况。

6.3-3 证明:在任一含n个元素的堆中,至多有向下取整n/2^(h+1)个高度为h的结点。

n个元素的堆中,总高度为H,则2^0+2^1+...+2^H=n =>2^(H+1)-1=n

利用数学归纳法:

当h=0(最底层的结点相对于叶子结点的高度为0,注意不是深度哦!)时,那么有n/2^(0+1)=

(2^(H+1)-1)/2=2^H-1/2=向下取整(2^H-1/2)=2^H 这个正好是完全二叉树最底层的结点数。当然

在堆中最底层可能结点数不满,那么就要小于这个值,所以当h=0时,至多有向下取整n/2^(h+1)个

高度为h的结点。得证!

假设h=k时,至多有向下取整n/2^(k+1)个高度为h的结点成立。

那么h=k(除了k=0层结点可能不满,其余k>0层都是满的。这是堆的定义)时,就有

(2^(H+1)-1)/2^(k+1)个结点。

那么h=k+1时,也就是比高度为k的高一层(根据高度定义和完全二叉树性质还有k>0的条件),那么

h=k+1结点数正好是h=k的一半,所以就应该有(1/2)(2^(H+1)-1)/2^(k+1)个结点,那么这个式子

可以转换为(2^(H+1)-1)/2^((k+1)+1)=n/2^(h+1),所以h=k+1时,符合题意。问题得证。

6.4-1 参照图6-4,说明 HEAPSORT在数组A={5,13,2,25,7,17,20,8,4}上的操作过程。

build:25 13 20 8 7 17 2 5 4

i=9:20 13 17 8 7 4 2 (25)

i=8:17 13 5 8 7 4 2 (20,25)

i=7:13 8 5 2 7 4 (17,20,25)

i=6:8 7 5 2 4 (13,17,20,25)

i=5:7 4 5 2 (8,13,17,20,25)

i=4:5 4 2 (7,8,13,17,20,25)

i=3:4 2 (5,7,8,13,17,20,25)

i=2:2 (4,5,7,8,13,17,20,25)

6.4-2 试分析在使用下列循环不变量时,HEAPSORT的正确性:

在算法的第2-5行for循环每次迭代开始时,子数组A[1..i]是一个包含了数组A[1..n]中第i小元素

的最大堆,而子数组A[i+1..n]包含了数组A[1..n]中已排序的n-i个最大元素?

初始化:

在for循环开始前,子数组A[1..n]是一个包含了数组A[1..n]中第n小元素的最大堆,而子数组

A[n+1..n]包含了数组A[1..n]中已排序的n-n=0个最大元素。

保持:

为了看到每次迭代都维护这个循环不变量。注意到A[1]与A[i]交换后,A[i]是当前堆A[1..i]的最

小元素同时也是堆中第一个元素,而A[1]是子数组A[i+1..n]的第一个元素。在进行了

A.heap-size-1后,这个子数组A[1..i]就减少了一个元素,而减少元素后的最后一个元素是新的i

元素。子数组A[i+1..n]增加了1个元素。当进行了MAX-HEAPIFY(A,1),这里的1就是交换后堆中第

一个元素也是最小元素,调用MAX-HEAPIFY(A,1)后,第一个元素就又是最大元素了,这个堆就是

最大堆了,然后再次用这个A[1]与A[i]交换后.....再次进行上面的循环。

终止:

过程终止时,i=1,根据循环不变量,有每个结点2...n都是最大堆的根,特别需要指出i=1时无需

调用函数,因为所有元素已经排好了。

6.4-3 对于一个按升序排列的包含n个元素的有序数组A来说,HEAPSORT的时间复杂度是多少?如

果A是降序呢?

升序时,建堆时,进行了n次MAX-HEAPIFY(A,i)调用。每次调用时,都要达到最坏运行时间lgn,

所以建堆时的时间复杂度O(nlgn),在对建好的最大堆排序时,又调用了n次MAX-HEAPIFY(A,i),

每次A[1]与A[i]交换后,MAX-HEAPIFY(A,i)都要进行lgn次,所以这n次循环的时间复杂度是O(nlgn),

所以总的时间复杂度是O(nlgn)+O(nlgn)=O(nlgn)

降序时,建堆时,由于堆已经是最大堆了,所以进行n次MAX-HEAPIFY(A,i)调用时,

MAX-HEAPIFY(A,i)时间复杂度是0,而建堆时的时间复杂度O(n),在对建好的最大堆排序时,又调

用了n次MAX-HEAPIFY(A,i),每次A[1]与A[i]交换后,MAX-HEAPIFY(A,i)都要进行lgn次,所以这n

次循环的时间复杂度是O(nlgn),所以总的时间复杂度是O(n)+O(nlgn)=O(nlgn)

6.4-4 证明:在最坏情况下,HEAPSORT的时间复杂度是Ω(nlgn).

HEAPSORT最坏情况就等于build函数与调用n次循环MAX-HEAPIFY(A,i)最坏时间,而build函数最坏

运行时间就等于MAX-HEAPIFY(A,i)最坏运行时间,建堆时和for(i=A.lengthdown to 2)循环时,

MAX-HEAPIFY(A,i)都要达到最坏时间T=Ω(lgn)(习题6.2-6的结论),而建堆和循环时,都进行了

n次循环,所以Ω(nlgn)(建堆)+Ω(nlgn)(循环)=Ω(nlgn)

6.4-5 证明:在所有元素都不同的情况下,HEAPSORT的时间复杂度是Ω(nlgn)

这个可以查看第二部分开篇引言,里面有关排序算法,堆排序是比较排序算法,第八章介绍的决策

树模型,可用来研究比较排序算法性能局限。使用这个模型,我们可以证明任意比较排序算法n个

元素的最坏运行时间的下界是Ω(nlgn).

既然是任意的n个元素也就包括了所有元素不同情况,而所用的方法是还未学到的决策树模型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: