二叉堆可以看做一个近似的完全二叉树,所以一般用数组来组织。

二叉堆可以分为两种形式:最大堆和最小堆。最大堆顾名思义,它的每个结点的值不能超过其父结点的值,因此堆中最大元素存放在根结点中。最小堆的组织方式刚好与最大堆相反,它的最小元素存放在根结点中。

维护堆性质最重要的两个算法就是向上维护和向下维护。简而言之,例如最大堆中根结点的值小于其子结点的值,这个时候就要向下维护,把根结点逐级下降到适合的位置。显而易见地,向上维护就是子结点的值比其父结点大时(最大堆中),将结点逐级上升到合适的位置。这两个方法保证堆的性质不会被破坏。

堆经常用来实现优先队列,最大堆就对应最大优先队列,最小堆同上。因为通过关键字来查找堆中具体元素的位置比较麻烦,所以一般通过在堆中存储对象的句柄,在对应的对象中也存储对应堆元素的句柄来直接定位到元素的位置。

二叉堆是堆中最容易实现的一种,也算是用的比较广泛的一种。我下面的代码给出了最大堆和最小堆的一部分关键操作,另外一部分则挑选其中一种来实现。

代码如下:(仅供参考)

  1. class Node {
  2. public :
  3. int value;
  4. public :
  5. Node(int v = ) : value(v) {}
  6. };
  7.  
  8. class Heap {
  9. vector<Node> heap;
  10. int heap_size;
  11.  
  12. int Left(int i) {return (i << ) + ;} //下标从0开始
  13. int Right(int i) {return Left(i) + ;}
  14. int Parent(int i) {return (i - ) >> ;}
  15. void MaxHeapify(int i); //使结点i维持最大堆性质(向下维护)
  16. void MinHeapify(int i); //使结点i维持最小堆性质(向下维护)
  17. void IncreaseKey(int i, int k); //将结点i的value上升到k(向上维护)
  18. public :
  19. Heap() : heap_size() {}
  20. Heap(vector<Node> &t) : heap(t), heap_size(t.size()) {}
  21. void BuildMaxHeap(); //建立最大堆,时间复杂度O(n);
  22. void BuildMinHeap(); //建立最小堆,时间复杂度O(n);
  23. void MinHeapSort(); //从小到大排序,时间复杂度O(nlgn);
  24. void MaxHeapSort(); //从大到小排序,时间复杂度O(nlgn);
  25. //以下函数仅在最大堆下进行
  26. void Insert(int k); //插入一个元素(最大堆)
  27. void Delete(int i); //删除一个元素(最大堆)
  28. Node Maximum(); //返回value最大的元素
  29. Node ExtractMax(); //去掉并返回value最大的元素
  30. //union two heap:union the vector of the two heaps, and call BuildMaxHeap()
  31. int Size() {return heap.size();} //返回vector的元素个数
  32. void PrintAll() {
  33. for (auto i : heap)
  34. cout << i.value << ends;
  35. cout << endl;
  36. }
  37. };
  38.  
  39. void Heap::MaxHeapify(const int i) {
  40. int largest;
  41. if (Left(i) < heap_size && heap[Left(i)].value > heap[i].value)
  42. largest = Left(i);
  43. else
  44. largest = i;
  45. if (Right(i) < heap_size && heap[Right(i)].value > heap[largest].value)
  46. largest = Right(i);
  47. if (largest != i) {
  48. swap(heap[i], heap[largest]);
  49. MaxHeapify(largest);
  50. }
  51. }
  52.  
  53. void Heap::MinHeapify(const int i) {
  54. int least;
  55. if (Left(i) < heap_size && heap[Left(i)].value < heap[i].value)
  56. least = Left(i);
  57. else
  58. least = i;
  59. if (Right(i) < heap_size && heap[Right(i)].value < heap[least].value)
  60. least = Right(i);
  61. if (least != i) {
  62. swap(heap[i], heap[least]);
  63. MinHeapify(least);
  64. }
  65. }
  66.  
  67. void Heap::BuildMaxHeap() {
  68. heap_size = heap.size();
  69. for (int i = Parent(heap_size - ); i >= ; --i)
  70. MaxHeapify(i);
  71. }
  72.  
  73. void Heap::BuildMinHeap() {
  74. heap_size = heap.size();
  75. for (int i = Parent(heap_size - ); i >= ; --i)
  76. MinHeapify(i);
  77. }
  78.  
  79. void Heap::MinHeapSort() {
  80. BuildMaxHeap();
  81. for (int i = heap.size() - ; i > ; --i) {
  82. swap(heap[i], heap[]);
  83. --heap_size;
  84. MaxHeapify();
  85. }
  86. }
  87.  
  88. void Heap::MaxHeapSort() {
  89. BuildMinHeap();
  90. for (int i = heap.size() - ; i > ; --i) {
  91. swap(heap[i], heap[]);
  92. --heap_size;
  93. MinHeapify();
  94. }
  95. }
  96.  
  97. void Heap::Insert(int k) {
  98. heap.push_back(INT_MIN);
  99. IncreaseKey(heap.size() - , k);
  100. }
  101.  
  102. void Heap::Delete(int i) {
  103. if (heap[heap.size() - ].value > heap[i].value) {
  104. IncreaseKey(i, heap[heap.size() - ].value);
  105. heap.pop_back();
  106. } else {
  107. heap[i] = heap[heap.size() - ];
  108. heap.pop_back();
  109. heap_size = heap.size();
  110. MaxHeapify(i);
  111. }
  112. }
  113.  
  114. Node Heap::Maximum() {
  115. return heap[];
  116. }
  117.  
  118. Node Heap::ExtractMax() {
  119. Node max = heap[];
  120. heap[] = heap[heap.size() - ];
  121. heap.pop_back();
  122. MaxHeapify();
  123. return max;
  124. }
  125.  
  126. void Heap::IncreaseKey(int i, int k) {
  127. if (k <= heap[i].value)
  128. return ;
  129. while (i > && heap[Parent(i)].value < k) {
  130. heap[i] = heap[Parent(i)];
  131. i = Parent(i);
  132. }
  133. heap[i].value = k;
  134. }

binary-heap(二叉堆)原理及C++代码实现的更多相关文章

  1. Binary Heap(二叉堆) - 堆排序

    这篇的主题主要是Heapsort(堆排序),下一篇ADT数据结构随笔再谈谈 - 优先队列(堆). 首先,我们先来了解一点与堆相关的东西.堆可以实现优先队列(Priority Queue),看到队列,我 ...

  2. 【数据结构与算法Python版学习笔记】树——利用二叉堆实现优先级队列

    概念 队列有一个重要的变体,叫作优先级队列. 和队列一样,优先级队列从头部移除元素,不过元素的逻辑顺序是由优先级决定的. 优先级最高的元素在最前,优先级最低的元素在最后. 实现优先级队列的经典方法是使 ...

  3. 堆(Heap)和二叉堆(Binary heap)

    堆(Heap) The operations commonly performed with a heap are: create-heap: create an empty heap heapify ...

  4. 二叉堆(binary heap)

    堆(heap) 亦被称为:优先队列(priority queue),是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.在队列中,调度程序反复提取队列中第一个作业并运行,因 ...

  5. 二叉堆(binary heap)—— 优先队列的实现

    二叉堆因为对应着一棵完全二叉树,因而可以通过线性数组的方式实现. 注意,数组第 0 个位置上的元素,作为根,还是第 1 个位置上的元素作为根? 本文给出的实现,以数组第 1 个位置上的元素作为根,则其 ...

  6. 数据结构 之 二叉堆(Heap)

    注:本节主要讨论最大堆(最小堆同理). 一.堆的概念     堆,又称二叉堆.同二叉查找树一样,堆也有两个性质,即结构性和堆序性.     1.结构性质:     堆是一棵被完全填满的二叉树,有可能的 ...

  7. C# 实现简单的 Heap 堆(二叉堆)

    如题,C#  实现简单的二叉堆的 Push() 和 Pop(), 如有不足欢迎指正. 另外,在C#中使用 Heap 的相似功能可以考虑使用:Priority Queues,SortedDictiona ...

  8. 【nodejs原理&源码杂记(8)】Timer模块与基于二叉堆的定时器

    [摘要] timers模块部分源码和定时器原理 示例代码托管在:http://www.github.com/dashnowords/blogs 一.概述 Timer模块相关的逻辑较为复杂,不仅包含Ja ...

  9. 【nodejs原理&源码杂记(8)】Timer模块与基于二叉堆的定时器

    目录 一.概述 二. 数据结构 2.1 链表 2.2 二叉堆 三. 从setTimeout理解Timer模块源码 3.1 timers.js中的定义 3.2 Timeout类定义 3.3 active ...

随机推荐

  1. 当spring单元测试需要用到临时表的时候

    需要将整个单元测试的方法交给spring的事务管理器控制. 两种解决方法: 1.加载的spring配置文件中advice要切到需要测试的方法. 2.单元测试类继承AbstractTransaction ...

  2. 关于GAN的一些笔记

    目录 1 Divergence 1.1 Kullback–Leibler divergence 1.2 Jensen–Shannon divergence 1.3 Wasserstein distan ...

  3. CPU的成本构成

    1)设计成本: 工程师的工资,EDA等开发工具的费用.设备费用.场地费用等等. 2)硬件成本: 硬件成本=(晶片成本+掩膜成本+封装.测试成本)/成品率 1.晶片成本 一片硅晶圆 晶片成本=晶圆成本/ ...

  4. opencv vs2013提示缺少Qedit.h问题

    #pragma include_alias( "dxtrans.h", "qedit.h" ) #define __IDxtCompositor_INTERFA ...

  5. dp--悬线dp P4147 玉蟾宫

    题目背景 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. 题目描述 这片土地被分成N*M个格子,每个格子里写着'R'或者'F ...

  6. sql注入入门--基本命令

    本文转载自http://blog.csdn.net/zgyulongfei/article/details/41017493 本文仅献给想学习渗透测试的sqlmap小白,大牛请绕过. > > ...

  7. Odd sum (对本菜鸡来说是个极坑题)

    https://codeforces.com/problemset/problem/797/B time limit per test 1 second memory limit per test 2 ...

  8. python刷LeetCode:5. 最长回文子串

    难度等级:中等 题目描述: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad"输出: "bab& ...

  9. VNC/XRDP/XDMCP尝试

    (记得安装X Window System等 可参考链接https://www.linuxidc.com/Linux/2017-10/147646.htm) 看本文档时可以参考 https://blog ...

  10. shell脚本判断进程是否运行

    zzx@zzx120:~$ if ps aux | grep "python"|grep -v grep > /dev/null             #$?的值不同 th ...