`
gaofen100
  • 浏览: 1228039 次
文章分类
社区版块
存档分类
最新评论

堆(heap)的定义及其算法分析

 
阅读更多

堆(heap)是与二叉查找树类似的ADT。但又不同于二叉查找树,主要体现在两个方面。第一,可将二叉查找树看着是有序的,而堆是有序的,这一概念较弱。不过,为使优先队列操作有效执行,这完全满足要求。第二,二叉查找树有多种不同形状,而堆总是完全二叉树。
堆是完全二叉树,可以为空,或者:
(1)根包含的查找关键字大于或等于各个孩子的查找关键字。
(2)根包含作为子树的堆。
在这个堆的定义中,根项包含的查找关键字最大。这样的堆称为maxheap。相对而言,minheap将包含最小查找关键字的项放在根中。
堆是完全二叉树,因此,若了解堆的最大规模,则可以用二叉树的基于数组的实现。图1显示堆及其数组表示。堆节点中的查找关键字大于或等于节点的孩子的查找关键字。另外,在堆中,孩子的查找关键字相互无关:换言之,并不知道那个孩子包含的查找关键字更大。


图1 堆及数组表示形式

堆的基于数组的实现
* items :堆项数组
* size :表示堆中的项数的整数
数组items对应于树的基于数组的表示。在下面的讨论中,为简化起见,假设堆项是整数。
heapDelete
首先考虑heapDelete操作。堆中最大的查找关键字在什么位置?因为各个节点的查找关键字都大于或等于任意一个孩子的查找关键字,所以最大的查找关键字一定在树根中,这样,heapDelete操作的第1步为:
// return the item in the root
rootitem=item[0];
这很简单,但也必须删除根。再删除根后,将留下两个分离的堆,如图2-a所示。因此,需要将其余点在转化为一个堆。在开始转换的时候,取出树中最后一个节点的项,并将其放在根中,如下所示:
//copy the item from the last node into the root
item[0]=item[size-1];
//remove the last node
--size
如图2-b所示,给步骤的结果不一定是堆,不过,这是一棵完全二叉树,左右子树都是堆。唯一的问题是,根项可能不在正确的位置,这样的结构称为半堆(semiheap)。需要一种方式,将半堆转化为堆。一种策略是使根项逐渐下移,直到进入处于正确的位置的节点停止。为此,首先比较半堆根的查找关键字与孩子的查找关键字。如果根的查找关键字小于孩子的查找关键字中的比较大者,则交换根与较大孩子的项,所谓较大孩子,即查找关键字大于另一个孩子的查找关键字。


图2 (a)分离堆 (b)半堆
图3显示heapDelete操作。只做了一次交换,值5就下移至正确的位置:不过,一般情况都需要多次交换。实际上,一旦交换了根项和较大孩子C的项,C就成为半堆的根(注意,C并不移动,更改的是它的值)。该策略引出了下面的迭归算法。


图3 从堆中删除


图4演示heapRebuild 的递归调用。


图4 heapRebuild的递归调用。
heapDelete操作使用heapRebuilt。如下所示:
//return the item from the last node into the root
rootItem=item[0];
//copy the item from the last node into the root
items[0]=items[size-1];
//remove the last node
--size;
//transform the semiheap back into a heap
heapRebuild(items,0,size);
简要分析heapDelete的效率。树存储在数组中,为删除节点,需要交换数组元素,而不是简单的修改几个指针。这些交换值得关注,但不意味着效率低下。最多交换数组元素多少次?在heapDelete将树中最后一个节点的项复制到根之后,heapRebuilt在树中下移此项,直到适当的位置,在最坏的情况下,项从根出发,沿单个路径下移,到达叶子。因此,heapRebuilt必须交换的数组项数不大于树的高度。包含n个节点的完全二叉树的高度为[log2(n+1)](大于log2(n+1)的最小整数)。每个交换需要移动3次数据。因此,heapDelete需要的数据移动次数为3*[log2(n+1)]+1所以,heapDelete为O(log n),实际上,这非常有效。
heapInsert
heapInsert 算法的策略与heapDelete正好相反。在树低插入一个新项,然后上移到适当位置,如图5所示。上移节点很容易,因为items[i](而不是根)节点总存储在items[(i-1)/2]中。heapInsert操作的伪码如下:


图5 在堆中插入

heapInsert的效率与heapDelete相同,换言之,在最坏的情况下,heapInset必须交换从叶子到根的路径上的数组元素。故交换次数不超过树高。完全二叉树的高度为[log2(n+1)],因此heapInsert也是O(log n)。

分享到:
评论

相关推荐

    算法分析与设计 期末大作业.doc

    《算法分析与设计》课程是计算机科学中至关重要的一门课,它主要研究如何高效地解决计算问题。在本篇期末大作业中,我们将探讨三种基于分治策略的算法:寻找数组中的最大值、构建大顶堆以及归并排序与快速排序的实现...

    数据结构与算法分析C++描述

    根据提供的文件信息,我们可以从标题、描述以及部分章节目录中提炼出有关“数据结构与算法分析C++描述”的关键知识点。 ### 数据结构与算法分析C++描述 #### 标题解读: - **数据结构**:计算机科学中的一个核心...

    算法设计与分析课件PPT

    1. **第一章:算法分析基本概念** - 算法:定义、特性与分类 - 时间复杂度和空间复杂度:衡量算法效率的重要指标 - 大O符号表示法:描述算法运行速度的渐进上界 - 最好情况、最坏情况和平均情况分析 2. **第四...

    c语言实现堆排序

    这里定义了一个`SqList`结构体用于存储堆排序所需的动态数组及其相关信息。 #### 2. 基础功能函数 - `InitList_Sq`:初始化列表,分配内存空间。 - `Load_Sq`:加载列表,打印当前列表中的元素。 - `ListInsert_Sq`...

    堆排序及优先队列源代码_上机c++ 添加元素 删除最大节点

    堆排序是一种基于比较的排序算法,它利用堆这种数据结构的特性进行排序。堆可以分为大顶堆(Max Heap)和小顶堆(Min Heap)。在大顶堆中,任意节点的值总是大于或等于其子节点的值;而在小顶堆中,则是任意节点的值...

    算法导论答案

    - **6.1-1** 堆的定义及其性质。 - **6.1-2** 堆的构建方法。 - **6.1-3** 堆排序的基本思想。 - **6.1-4** 堆排序的时间复杂度分析。 - **6.1-5** 堆排序的空间复杂度分析。 - **6.1-6** 堆排序的稳定性分析。 - **...

    算法导论 练习题答案

    - 常见的数学函数及其在算法分析中的应用,如对数函数、多项式函数等。 #### 4. 分治法 - **标题**:“Divide-and-Conquer” - **描述**:这部分深入探讨了分治法这一经典算法设计技术。 - **重要知识点**: - **...

    算法导论英文版

    - **3.2 标准记号和常用函数**:列举了一些常用的数学函数和它们在算法分析中的应用。 - **第四章:分治法** - **4.1 最大子数组问题**:通过一个具体的实例介绍了分治策略的应用。 - **4.2 斯特拉斯矩阵乘法...

    ACM_算法模板集.pdf

    - 定义:排列与组合的基本概念及其算法实现。 - **二维线段树 (2D Segment Tree)** - 定义:在线性空间上实现二维区间的查询和更新。 - **稳定婚姻匹配 (Stable Marriage Problem)** - 定义:寻找满足稳定条件的...

    包含贪心算法的定义及python代码部分实现

    ### 贪心算法概述 贪心算法是一种重要的优化算法,其核心思想在于在每一步操作中都作出局部最优的选择,希望通过这种方式...因此,在使用贪心算法之前,需要仔细分析问题特性,确保所选策略能够有效地应用于具体问题。

    算法实验源代码

    `pop_heap`函数则将堆顶元素下沉至正确的位置,并将原堆顶元素移除堆结构,但不会立即从容器中删除。 ```cpp vec.pop_back(); ``` 通过调用`pop_back`方法从容器中删除最后一个元素,即原堆顶元素。结合这些操作,...

    清华大学邓俊辉数据结构讲义

    - **最大流问题**:介绍最大流问题的定义及其算法解决方案。 #### 十二、高级排序算法 - **快速排序**:详细介绍快速排序的原理及其优化方法。 - **归并排序**:讲解归并排序的实现原理及其实现细节。 - **选择与...

    算法导论--教师手册

    - **堆排序(Heap Sort)**:章节6介绍了堆排序算法,这是一种基于二叉堆数据结构的比较排序算法。堆排序具有O(n log n)的时间复杂度,适用于大数据集的排序。 - **快速排序(Quick Sort)**:章节7讲解了快速排序...

Global site tag (gtag.js) - Google Analytics