《算法导论》第六章----堆排序练习(证明)(完整版)
2013-09-16 20:47
676 查看
《算法导论》学习记录目录
欢迎指出其中的错误和交流。
关于堆排序的具体介绍和C代码实现见该链接。
算导关于堆排序的练习主要是一些证明,可以帮助理解堆的特征。部分练习是图示过程,这些练习认真用笔过一次会很有收获。
1.在高度为h的堆中,最多和最少的元素个数是多少?
最多:底层全满;1 + 2^1 + 2^2 + ...... + 2^h,等比数列求和得2^(h+1) - 1
最少:底层只有一个节点;1 + 2^1 + 2^2 + ...... + 2^(h-1) + 1,等比数列求和得2^h - 1 + 1 = 2^h
2.证明:含n个元素的堆的高度为floor(lgn)
假设n个元素的堆的高度为h。由上题得2^h <= n <= 2^(h+1) - 1,因此h <= lgn < h+1。
根据floor 和 ceiling 函数的性质
View Code
7.证明:对于一个大小为n的堆,max_heapify的最坏运行时间为Ω(lgn)。(提示:对于n个节点的堆,恰当地设置每个节点的值,使得从根节点到叶节点的路径上的每个节点都递归调用max_heapify)。
假设大小为n的堆的高度为h
首先如何使得从根节点到叶节点的路径上的每个节点都递归调用max_heapify?每次调用后的子树都符合子树的根节点小于左右儿子节点,则最初的根节点的值比所有左右儿子的值都小。接着要考虑的就是路径-----如何使得从根节点到叶节点的路径更长(最坏的情况)?“堆数据结构是一种数组对象,可以视为一棵完全二叉树。树的每一层都是填满的,最后一层除外(最后一层从一个节点的左子树开始填)”------《算导》原文。因此每次根节点与其左儿子节点交换,路径会是最长的,则所有左子树的值大于或等于右子树。这样设置,max_heapify会调用h次,所以运行时间为Θ(h),即Θ(lgn)。根据大Θ符号的定义(链接为维基),详细见算导第三章----函数的增长,因此的得最坏运行时间为Ω(lgn)。
8.证明:在任一含n个元素的堆中,最多有ceiling(n / 2^(h+1))个高度为h的节点。
证明为算导的答案:(答案很详细)
9.对于一个其所有n个元素已按递增序排列的数组A,堆排序的运行时间是多少?若A的元素呈降序呢?
递增序排列和递减序(降序)一样:先建堆,运行时间为O(n),然后将数组最后一个与第一个交换,数组大小减一,在进行max_heapify(维持最大堆的性质),依次重复操作(O(n) * O(lgn) = O(n*lgn))
因此运行时间为O(n) * O(lgn) = O(n*lgn)
10.证明:堆排序的最坏情况运行时间为Ω(n*lgn)。
堆排序属于比较排序,比较排序的最坏情况运行时间的下界为Ω(n*lgn),见算导第八章第一节。
11.证明:在所有元素都不相同时,堆排序的最佳运行时间为Ω(n*lgn)。
无论数组是否已排序,都要调用n - 1次max_heapify函数,可以得最佳运行时间为Ω(n*lgn)。
欢迎指出其中的错误和交流。
关于堆排序的具体介绍和C代码实现见该链接。
算导关于堆排序的练习主要是一些证明,可以帮助理解堆的特征。部分练习是图示过程,这些练习认真用笔过一次会很有收获。
1.在高度为h的堆中,最多和最少的元素个数是多少?
最多:底层全满;1 + 2^1 + 2^2 + ...... + 2^h,等比数列求和得2^(h+1) - 1
最少:底层只有一个节点;1 + 2^1 + 2^2 + ...... + 2^(h-1) + 1,等比数列求和得2^h - 1 + 1 = 2^h
2.证明:含n个元素的堆的高度为floor(lgn)
假设n个元素的堆的高度为h。由上题得2^h <= n <= 2^(h+1) - 1,因此h <= lgn < h+1。
根据floor 和 ceiling 函数的性质
void max_heapify(int A[], int length, int i){ int l, r; int largest, temp; while(i <= length){ l = 2 * i; r = 2 * i + 1; if(l <= length && A[l] > A[i]) largest = l; else largest = i; if(r <= length && A[r] > A[largest]) largest = r; if(largest != i){ temp = A[largest]; A[largest] = A[i]; A[i] = temp; i = largest; } else break; } }
View Code
7.证明:对于一个大小为n的堆,max_heapify的最坏运行时间为Ω(lgn)。(提示:对于n个节点的堆,恰当地设置每个节点的值,使得从根节点到叶节点的路径上的每个节点都递归调用max_heapify)。
假设大小为n的堆的高度为h
首先如何使得从根节点到叶节点的路径上的每个节点都递归调用max_heapify?每次调用后的子树都符合子树的根节点小于左右儿子节点,则最初的根节点的值比所有左右儿子的值都小。接着要考虑的就是路径-----如何使得从根节点到叶节点的路径更长(最坏的情况)?“堆数据结构是一种数组对象,可以视为一棵完全二叉树。树的每一层都是填满的,最后一层除外(最后一层从一个节点的左子树开始填)”------《算导》原文。因此每次根节点与其左儿子节点交换,路径会是最长的,则所有左子树的值大于或等于右子树。这样设置,max_heapify会调用h次,所以运行时间为Θ(h),即Θ(lgn)。根据大Θ符号的定义(链接为维基),详细见算导第三章----函数的增长,因此的得最坏运行时间为Ω(lgn)。
8.证明:在任一含n个元素的堆中,最多有ceiling(n / 2^(h+1))个高度为h的节点。
证明为算导的答案:(答案很详细)
9.对于一个其所有n个元素已按递增序排列的数组A,堆排序的运行时间是多少?若A的元素呈降序呢?
递增序排列和递减序(降序)一样:先建堆,运行时间为O(n),然后将数组最后一个与第一个交换,数组大小减一,在进行max_heapify(维持最大堆的性质),依次重复操作(O(n) * O(lgn) = O(n*lgn))
因此运行时间为O(n) * O(lgn) = O(n*lgn)
10.证明:堆排序的最坏情况运行时间为Ω(n*lgn)。
堆排序属于比较排序,比较排序的最坏情况运行时间的下界为Ω(n*lgn),见算导第八章第一节。
11.证明:在所有元素都不相同时,堆排序的最佳运行时间为Ω(n*lgn)。
无论数组是否已排序,都要调用n - 1次max_heapify函数,可以得最佳运行时间为Ω(n*lgn)。
相关文章推荐
- 算法导论详解(5) 第六章 堆排序
- 算法导论第六章 堆排序
- 算法导论第六章伪码转C++ ___堆排序
- 算法导论 第六章 堆排序
- 《算法导论》第六章----堆排序
- 算法导论笔记-第六章-堆排序
- 算法导论第六章 -- 堆排序
- 算法导论 第六章:堆排序
- 《算法导论》第六章“堆排序”习题解答
- 算法导论学习笔记-第六章-堆排序
- 《算法导论》学习笔记--第六章 堆排序
- 算法导论第六章总结:堆排序
- 《算法导论》第六章----优先级队列(代码实现+部分练习)
- 《算法导论》第六章----优先级队列(代码实现+部分练习)
- 算法导论 第六章 堆排序
- 学习《算法导论》第六章 堆排序 总结二
- 算法导论第六章 堆排序
- 算法导论第六章 堆排序
- 算法导论(第三版)第六章 堆排序的全部实现(堆排序,优先队列)
- 算法导论 第六章 堆排序 习题6.5-8 k路合并排序