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

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个元素也就包括了所有元素不同情况,而所用的方法是还未学到的决策树模型。

    原文作者:排序算法
    原文地址: https://blog.csdn.net/z84616995z/article/details/17763501
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞