以下转载自http://www.cnblogs.com/QG-whz/p/5173112.html

阅读目录

  • 0. 数据结构图文解析系列
  • 1. 二叉堆的定义
  • 2. 二叉堆的存储
  • 3. 二叉堆的具体实现
    • 3.1 二叉堆的抽象数据类型
    • 3.2 二叉堆的插入
    • 3.3 二叉堆的删除
    • 3.4 其余操作
  • 4. 二叉堆代码测试
  • 5. 大顶堆、小顶堆完整代码下载

正文

回到顶部

0. 数据结构图文解析系列

数据结构系列文章
数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现
数据结构图文解析之:栈的简介及C++模板实现
数据结构图文解析之:队列详解与C++模板实现
数据结构图文解析之:树的简介及二叉排序树C++模板实现.
数据结构图文解析之:AVL树详解及C++模板实现
数据结构图文解析之:二叉堆详解及C++模板实现
回到顶部

1. 二叉堆的定义

二叉堆是一种特殊的堆,二叉堆是完全二叉树或近似完全二叉树。二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆。
当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆。 当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆。

回到顶部

2. 二叉堆的存储

二叉堆一般使用数组来表示。请回忆一下二叉树的性质,其中有一条性质:

性质五:如果对一棵有n个节点的完全二叉树的节点按层序编号(从第一层开始到最下一层,每一层从左到右编号,从1开始编号),对任一节点i有:

  1. 如果i=1 ,则节点为根节点,没有双亲。
  2. 如果2 * i > n ,则节点i没有左孩子 ;否则其左孩子节点为2*i . (n为节点总数)
  3. 如果2 * i+1>n ,则节点i没有右孩子;否则其右孩子节点为2*1+1.

简单来说:

  1. 如果根节点在数组中的位置是1,第n个位置的子节点分别在2n 与 2n+1,第n个位置的双亲节点分别在⌊i /2⌋。因此,第1个位置的子节点在2和3.
  2. 如果根节点在数组中的位置是0,第n个位置的子节点分别在2n+1与2n+2,第n个位置的双亲节点分别在⌊(i-1) /2⌋。因此,第0个位置的子节点在1和2.

得益于数组的随机存储能力,我们能够很快确定堆中节点的父节点与子节点。

下面以大顶堆展示一下堆的数组存储。

在本文中,我们以大顶堆为例进行堆的讲解。本文大顶堆的根节点位置为0.

回到顶部

3. 二叉堆的具体实现

在二叉堆上可以进行插入节点、删除节点、取出堆顶元素等操作。

3.1 二叉堆的抽象数据类型

/*大顶堆类定义*/
template <typename T>
class MaxHeap { public: bool insert(T val); //往二叉堆中插入元素 bool remove(T data); //移除元素 void print(); //打印堆 T getTop(); //获取堆顶元素 bool createMaxHeap(T a[], int size);//根据指定的数组来创建一个最大堆 MaxHeap(int cap = 10); ~MaxHeap(); private: int capacity; //容量,也即是数组的大小 int size; //堆大小,也即是数组中有效元素的个数 T * heap; //底层的数组 private: void filterUp(int index); //从index所在节点,往根节点调整堆 void filterDown(int begin ,int end ); //从begin所在节点开始,向end方向调整堆 };
  1. 注意capacity与size的区别。capacity指的是数组的固有大小。size值数组中有效元素的个数,有效元素为组成堆的元素。
  2. heap为数组。

3.2 二叉堆的插入

在数组的最末尾插入新节点,然后自下而上地调整子节点与父节点的位置:比较当前结点与父节点的大小,若不满足大顶堆的性质,则交换两节点,从而使当前子树满足二叉堆的性质。时间复杂度为O(logn)。
当我们在上图的堆中插入元素12:

调整过程:

  1. 节点12添加在数组尾部,位置为11;
  2. 节点12的双亲位置为⌊11/2⌋ = 5,即节点6;节点12比节点6大,与节点6交换位置。交换后节点12的位置为5.
  3. 节点12的双亲位置为⌊ 5 /2⌋ = 2,即节点9;节点12比节点9大,与节点9交换位置。交换后节点12的位置为2.
  4. 节点12的双亲位置为⌊2/2⌋ = 1,即节点11;节点12比节点11大,与节点11交换位置。交换后节点12的位置为1.
  5. 12已经到达根节点,调整过程结束。

这个从下到上的调整过程为:

/*从下到上调整堆*/
/*插入元素时候使用*/
template <typename T> void MaxHeap<T>::filterUp(int index) { T value = heap[index]; //插入节点的值,图中的12 while (index > 0) //如果还未到达根节点,继续调整 { int indexParent = (index -1)/ 2; //求其双亲节点 if (value< heap[indexParent]) break; else { heap[index] = heap[indexParent]; index = indexParent; } } heap[index] = value; //12插入最后的位置 }; 

在真正编程的时候,为了效率我们不必进行节点的交换,直接用父节点的值覆盖子节点。最后把新节点插入它最后的位置即可。

基于这个调整函数,我们的插入函数为:

/*插入元素*/
template <typename T>
bool MaxHeap<T>::insert(T val) { if (size == capacity) //如果数组已满,则返回false return false; heap[size] = val; filterUp(size); size++; return true; };

3.3 二叉堆的删除

堆的删除是这样一个过程:用数组最末尾节点覆盖被删节点,再从该节点从上到下调整二叉堆。我们删除根节点12:

可能有人疑惑,删除后数组最末尾不是多了一个6吗?
的确,但我们把数组中有效元素的个数减少了一,最末尾的6并不是堆的组成元素。

这个从上到下的调整过程为:

/*从上到下调整堆*/
/*删除元素时候使用*/
template<typename T> void MaxHeap<T>::filterDown(int current,int end) { int child = current * 2 + 1; //当前结点的左孩子 T value = heap[current]; //保存当前结点的值 while (child <= end) { if (child < end && heap[child] < heap[child+1])//选出两个孩子中较大的孩子 child++; if (value>heap[child]) //无须调整;调整结束 break; else { heap[current] = heap[child]; //孩子节点覆盖当前结点 current = child; //向下移动 child = child * 2 + 1; } } heap[current] = value; };

基于调整函数的删除函数:

/*删除元素*/
template<typename T>
bool MaxHeap<T>::remove(T data) { if (size == 0) //如果堆是空的 return false; int index; for (index = 0; index < size; index++) //获取值在数组中的索引 { if (heap[index] == data) break; } if (index == size) //数组中没有该值 return false; heap[index] = heap[size - 1]; //使用最后一个节点来代替当前结点,然后再向下调整当前结点。 filterDown(index,size--); return true; };

3.4 其余操作

其余操作很简单,不在这里啰嗦。

/*打印大顶堆*/
template <typename T>
void MaxHeap<T>::print() { for (int i = 0; i < size; i++) cout << heap[i] << " "; }; /*获取堆顶元素*/ template <typename T> T MaxHeap<T>::getTop() { if (size != 0) return heap[0]; }; /*根据指定的数组来创建一个最大堆*/ template<typename T> bool MaxHeap<T>::createMapHeap(T a[], int size) { if (size > capacity) // 堆的容量不足以创建 return false; for (int i = 0; i < size; i++) { insert(a[i]); } return true; }; 
回到顶部

4. 二叉堆代码测试

测试代码:

int _tmain(int argc, _TCHAR* argv[])
{MaxHeap<int> heap(11); //逐个元素构建大顶堆 for (int i = 0; i < 10; i++) { heap.insert(i); } heap.print(); cout << endl; heap.remove(8); heap.print(); cout << endl; //根据指定的数组创建大顶堆 MaxHeap<int> heap2(11); int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; heap2.createMaxHeap(a, 10); heap2.print(); getchar(); return 0; } 

运行结果:

9 8 5 6 7 1 4 0 3 2 9 7 5 6 2 1 4 0 3 10 9 6 7 8 2 5 1 4 3
回到顶部

5. 大顶堆、小顶堆完整代码下载

二叉堆完整代码:https://github.com/huanzheWu/Data-Structure/blob/master/MaxHeap/MaxHeap/MaxHeap.h
小顶堆完整代码:https://github.com/huanzheWu/Data-Structure/blob/master/MinHeap/MinHeap/MinHeap.h
以上转载自http://www.cnblogs.com/QG-whz/p/5173112.html

转载于:https://www.cnblogs.com/hualian/p/11159713.html

【转】数据结构图文解析之:二叉堆详解及C++模板实现相关推荐

  1. 二叉堆详解实现优先级队列

    二叉堆详解实现优先级队列 文章目录 二叉堆详解实现优先级队列 一.二叉堆概览 二.优先级队列概览 三.实现 swim 和 sink 四.实现 delMax 和 insert 五.最后总结 二叉堆(Bi ...

  2. 42. 盘点那些必问的数据结构算法题之二叉堆

    盘点那些必问的数据结构算法题之二叉堆 0 概述 1 二叉堆定义 2 保持堆的性质 3 建立最大堆 4 堆排序 5 优先级队列 参考资料 0 概述 本文要描述的堆是二叉堆.二叉堆是一种数组对象,可以被视 ...

  3. 【数据结构与算法】二叉堆V2.0的Java实现

    更新说明 我们在此前已经编写过简单版的二叉大根堆V1.0,这次,换成二叉小根堆,命名为二叉堆V2.0. 大家也知道,堆是完全二叉树,存储方式借助动态数组实现顺序存储,依赖于父子结点之间的index关系 ...

  4. 【数据结构与算法】二叉堆与二叉搜索树的区别

    问题描述 记得刚学习数据结构的时候,就容易混淆二叉堆和二叉搜索树,其实虽说堆也是一种完全二叉树,但二者差别还是挺大的,本文试做分析. 逻辑结构 二叉堆和二叉搜索树都是结点带权重,并在父子结点间满足某种 ...

  5. 数据结构之什么是二叉堆?

    文章目录 什么是二叉堆? 二叉堆的自我调整 插入节点 删除节点 构建二叉堆 最小二叉堆的实现 最小堆的构建 最小堆插入节点并上浮 最小堆删除节点并下沉 最小堆的完整代码实现 最后 什么是二叉堆? 二叉 ...

  6. AVL树(二叉平衡树)详解与实现

    公众号文章链接 AVL树概念 前面学习二叉查找树和二叉树的各种遍历,但是其查找效率不稳定(斜树),而二叉平衡树的用途更多.查找相比稳定很多.(欢迎关注数据结构专栏) AVL树是带有平衡条件的二叉查找树 ...

  7. 二叉搜索树详解--实现插入和删除

    目录 BST树概念 BST树操作 BST树的查找 BST树的插入 BST树的删除 实现一个自己的BST树 BSTNode类和BSTree类 查找操作; 插入操作: 删除操作: 应用: 二叉搜索树性能分 ...

  8. java二叉搜索树详解

    文章目录 一.概念 二.相关操作 2.0节点相关代码: 2.1查找 2.2插入 2.3删除(重难点) 2.4测试用例 三.小结 提示:以下是本篇文章正文内容,下面案例可供参考 一.概念 二叉搜索树又称 ...

  9. 【数据结构与算法】4.数据结构图文解析系列

    数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 数据结 ...

  10. 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

最新文章

  1. C++对象模型9——临时对象的生命周期、模板及实例化分析、内联函数
  2. Python实现 灰色关联分析 与结果可视化
  3. Flask框架后端开发常见错误处理(2018/11/14)
  4. 设置asp.net网站的信任等级
  5. PAT-A Sign In and Sign Out
  6. 好奇怪呀后面加什么标点_狗狗吃饭时奇怪的小动作,你知道代表什么吗?做个懂狗的好主人...
  7. html中列表、表格、合并单元格
  8. 解决uploadify在Firefox下丢失session的问题
  9. Redis集群添加数据报错(error) CLUSTERDOWN The cluster is down
  10. Leetcode 147 Insertion Sort List
  11. 解读《美国国家BIM标准》– BIM能力成熟度模型(六)
  12. IDEA配置JDK版本
  13. bios不识别 光驱固态_bios识别不到固态硬盘
  14. vscode CommandNotFoundError: Your shell has not been properly configured to use ‘conda activate‘.解决
  15. metamask连接不上本地私有节点,报错“无法获取链 IC,您的 RPC URL 地址是正确的么”
  16. 万人「变阵冲刺」,京东数科没有终点
  17. Quartz的整合与使用
  18. cmd命令方式启动服务
  19. 计算机学院学生工作办公室,上海交通大学-电子信息与电气工程学院-学生工作办公室...
  20. 转:windows.DNS.如何用自己的服务器做 DNS 域名解析,如何创建域名服务器?

热门文章

  1. 失败后的从容离开,无意之中也许会再次点亮希望之光
  2. 本周小结!(二叉树系列之四)
  3. codeforce 460B Little Dima and Equation
  4. M1 Mac 屏幕截图录像工具:CleanShot X
  5. 在 Mac 上如何放大或缩小?
  6. ConceptDraw Office for mac(跨平台图表办公程序)
  7. DropDMG for Mac(dmg打包软件)
  8. 如何保护Mac的数据安全?
  9. 数据库grant 授权
  10. 新时代的web与app开发