- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
第三节 堆及其应用 一、预备知识 完全二叉树: 如果一棵深度为K二叉树,1至k-1层的结点都是满的,即满足2i-1,只有最下面的一层的结点数小于2i-1,并且最下面一层的结点都集中在该层最左边的若干位置,则此二叉树称为完全二叉树。 二、堆的定义 堆结构是一种数组对象,它可以被视为一棵完全二叉树。树中每个结点与数组中存放该结点中值的那个元素相对应,如下图: 三、堆的性质 设数组A的长度为len,二叉树的结点个数为size,size≤len,则A[i]存储二叉树中编号为i的结点值(1≤i≤size),而A[size]以后的元素并不属于相应的堆,树的根为A[1],并且利用完全二叉树的性质,我们很容易求第i个结点的父结点(parent(i))、左孩子结点(left(i))、右孩子结点(right(i))的下标了,分别为:i/2、2i、2i+1; 更重要的是,堆具有这样一个性质,对除根以外的每个结点i,A[parent(i)]≥A[i]。即除根结点以外,所有结点的值都不得超过其父结点的值,这样就推出,堆中的最大元素存放在根结点中,且每一结点的子树中的结点值都小于等于该结点的值,这种堆又称为“大根堆”;反之,对除根以外的每个结点i,A[parent(i)]≤A[i]的堆,称为“小根堆”。 四、堆的操作 用堆的关键部分是两个操作:put操作,即往堆中加入一个元素;get操作,即从堆中取出并删除一个元素。 1、往堆中加入一个元素的算法(put)如下: (1)在堆尾加入一个元素,并把这个结点置为当前结点。 (2)比较当前结点和它父结点的大小 如果当前结点小于父结点,则交换它们的值,并把父结点置为当 前结点。转(2)。 如果当前结点大于等于父结点,则转(3)。 (3)结束。 重复n次put操作,即可建立一个小根堆。我们举一个例子看看具体过程:设n=10,10堆的数量分别为:3 5 1 7 6 4 2 5 4 1。 设一个堆结构heap[11],现在先考虑用put操作建一个小根堆,具体方法是每次读入一个数插入到堆尾,再通过调整使得满足堆的性质(从堆尾son=len开始,判断它与父结点son/2的大小,若heap[son]heap[son/2],则交换这两个数,且son=son/2,继续判断heap[son]与heap[son/2]的大小,……直到son=1或者heap[son]=heap[son/2]为止)。开始时堆的长度len=0。 实际上,我们也可以直接用完全二叉树的形式描述出这个过程,得到如下的一棵完全二叉树(堆): void put(int d) //heap[1]为堆顶 { int now, next; heap[++heap_size] = d; now = heap_size; while(now 1) { next = now 1; if(heap[now] = heap[next]) break; swap(heap[now], heap[next]); now = next; } } 使用C++标准模板库STL(需要头文件algorithm): void put(int d) { heap[++heap_size] = d; //push_heap(heap + 1, heap + heap_size + 1); //大根堆 push_heap(heap + 1, heap + heap_size + 1, greaterint()); //小根堆 } 2、从堆中取出并删除一个元素的算法(get)如下: (1)取出堆的根结点的值。 (2)把堆的最后一个结点(len)放到根的位置上,把根覆盖掉。把堆 的长度减一。 (3)把根结点置为当前父结点pa。 (4)如果pa无儿子(palen/2),则转(6);否则,把pa的两(或一) 个儿子中值最小的那个置为当前的子结点son。 (5)比较pa与son的值,如果fa的值小于或等于son,则转(6); 否则,交换这两个结点的值,把pa指向son,转(4)。 (6)结束。 int get() //heap[1]为堆顶 { int now=1, next, res= heap[1]; heap[1] = heap[heap_size--]; while(now * 2 = heap_size) { next = now * 2; if (next heap_
文档评论(0)