算法导论 第六章 思考题 6-1 用插入的方法建堆

BUILD-MAX-HEAP‘(A)
    heap-size[A]<-1
    for i <- 2 to length[A]
        do MAX-HEAP-INSERT(A, A[i])

如上,题目给出一种使用插入的办法建堆的算法,而书中6.4节给出的建堆算法如下:

BUILD-MAX-HEAP(A)
    heap-size[A] <-- length[A]
    for i <-- length[A] / 2 downto 1
        do MAX-HEAPIFY[A, i]

  可以发现元素调整的方向恰好反过来了。

现在来考虑问题,第一问看两种方法得到的堆会不会总是一样的,答案是不会,这可以通过举例来说明:

并不是总是一样的,考虑这样一个情况,有一个n=3的数组,其中a[1]<a[2]<a[3],那么在用传统的建堆过程a[1]会变成a[3]的右儿子,而利用BUILD-MAX-HEAP‘(A),a[1]则会变成a[3]的左儿子,于是,建立的堆是不同的。

第二问考虑时间复杂度。可以先参看书中6.4节证明BUILD-MAX-HEAP的时间复杂度时的情形:

在任意高度h上,至多有n/2^(h +1) + 1个节点,而max-heapify作用在高度为h的节点上的时间为O(h),于是得到时间复杂度为:

利用附录中的公式可得建堆的时间复杂度为线性时间O(n)。但是题目中提出的插入建堆方法,元素调整的方向刚好相反,也就是某高度为h的元素作用时间应该变成

O(logn - h),这样的话,代入同样的公式中求得的时间复杂度就变成,O(nlogn)了

时间: 2024-12-22 17:25:17

算法导论 第六章 思考题 6-1 用插入的方法建堆的相关文章

算法导论 第六章 思考题 6-3 d叉堆

d叉堆的实现相对于二叉堆变化不大,首先看它如何用数组表示. 考虑一个索引从1开始的数组,一个结点i最多可以有d个子结点,编号从id - (d - 2) 到 id + 1. 从而可以知道一个结点i的父结点计算方法为: (i + d - 2) / d. 第二个问题是 一个含有n个元素的d叉堆的高度,就是一个简单的等比数列的问题,可以知道的是一颗高度为h的满d叉树所含的结点数目为(d^(h +1) - 1) / (d - 1) 从而一颗含有 n个结点的d叉树满足的条件为: ,从而得到高度h为: 接下来

算法导论 第六章 思考题6-3 Young氏矩阵

这题利用二叉堆维持堆性质的办法来维持Young氏矩阵的性质,题目提示中写得很清楚,不过确实容易转不过弯来. a,b两问很简单.直接看c小问: 按照Young氏矩阵的性质,最小值肯定在左上角取得,问题在于取出最小值后如何保持矩阵的性质.可以参照max_heapify中的做法,先取出最小值,然后将矩阵左上角置为最大值,这样左上角处的元素必然导致Young氏矩阵的性质违背,于是考虑该元素右边的元素和该元素下边的元素,问题是该与右边元素交换还是与下边元素交换呢?可以发现,如果与T(右)和T(下)中较小的

算法导论第六章 堆排序

堆的时间复杂度是建O(n),时间复杂度为堆排序O(NLogN),细节如以下的算法看到: #include <iostream> using namespace std; void swap(int &i,int &j) { int temp=i; i=j; j=temp; } void shiftDown(int *A, int start,int len) { int temp=A[start]; int i=start; int j=2*i+1; while (j<l

算法导论第六章优先队列(二)

优先队列可以说是堆的一个非常重要的应用,和堆对应,优先队列也分最小优先队列和最大优先队列. 优先队列是一种用来维护由一组元素构成的集合S的数据结构,其中每一个元素都有一个关键字(key),关键字赋予了一个元素的优先级,故名为优先队列.之所以用堆来实现优先队列,我想最大的原因是堆很容易对元素按关键字进行排序. 优先队列的应用: 最大优先队列:其中最为典型的就是“共享计算机系统的作业调度”,通过记录各个作业的优先级,来调度一个作业的执行.删除和插入等操作. 最小优先队列:可以被用于“基于事件驱动的模

算法导论 第18章 思考题18-2 2-3-4树的链接与分裂,推广至B树

题目 2-3-4树是B树的特例,是度为2的B树.在B树这篇博客中,我们实现的B树是一个模板,因此要得到2-3-4树,即度为2的B树非常容易,只要如是声明就可以了--Btree<int,2> bt,其中int是所存元素类型. 在本题中,要实现的是2-3-4树的链接与分裂.参看红黑树的连接操作我们不难得到2-3-4树的链接方法.现在,我们对于2-3-4树的链接也予以推广,即实现任意度数的B树的链接和分裂. (a) B树高度的变化只有两种方式:一是在插入关键字的时候,根节点满,那么其要分裂,树长高:

算法导论第六章__实现优先队列

public class Priority_Queue { //储存的数组 private int A[]; //堆的大小 private int pile_Size=0; //如果找到指定值,返回 -1 private int NOT_FIND = -1; //堆容器的大小增量 private int INCREAT_CAPCITY=20; //堆容器大小 private static int INT_NUM=20; //构造函数1__不指定堆容器的大小,容器大小设置为默认大小,值:INT_N

算法导论第六章堆排序(一)

现在来看, 堆的含义大概有两种,一种是数据结构,一种是在一些语言中所定义的“垃圾回收机制”,如Java,在书本上的开篇强调了这两者,并强调若非特殊说明,皆把堆看做是一种数据结构. (二叉)堆的定义: 1)它是一个数组,可以被看成是一棵近似的完全二叉树,树上的每一个节点看做是数组中的每一个元素. 2)堆分为最大堆和最小堆,最大堆中每一棵子树的父节点的值大于孩子节点,最小堆则相反. 3)表示堆的数组A包括两个属性:A.length和A.heap_size.前者是数组元素的个数,后者是堆元素的个数,h

算法导论 第六章 堆排序

http://blog.csdn.net/mishifangxiangdefeng/article/details/7662515 http://www.cnblogs.com/Jiajun/archive/2013/05/31/3110256.html 这里练习6.3-3看http://blog.csdn.net/sailing_lqh/article/details/7381893的比较好理解

算法导论--第六章、堆排序

1. 堆的概念 堆的数据结构是一种数组对象:堆可以视作为一颗完全二叉树(其中,树的每一层都填满,最后一层可能除外):树中每个节点与数组中存放该节点值的元素对应: 堆可以划分为两类: a)     最大堆:除了根节点,有A[parent(i)] >= A[i],最大元素即根节点: b)     最小堆:除了根节点,有A[parent(i)] <= A[i],最小元素即根节点: 对于给定节点i,可以根据其在数组中的位置求出该节点的父亲节点PARENT(i)=i/2.左孩子LEFT(i) = 2*i