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

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

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

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

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

代码如下:(仅供参考)

 class Node {
public :
int value;
public :
Node(int v = ) : value(v) {}
}; class Heap {
vector<Node> heap;
int heap_size; int Left(int i) {return (i << ) + ;} //下标从0开始
int Right(int i) {return Left(i) + ;}
int Parent(int i) {return (i - ) >> ;}
void MaxHeapify(int i); //使结点i维持最大堆性质(向下维护)
void MinHeapify(int i); //使结点i维持最小堆性质(向下维护)
void IncreaseKey(int i, int k); //将结点i的value上升到k(向上维护)
public :
Heap() : heap_size() {}
Heap(vector<Node> &t) : heap(t), heap_size(t.size()) {}
void BuildMaxHeap(); //建立最大堆,时间复杂度O(n);
void BuildMinHeap(); //建立最小堆,时间复杂度O(n);
void MinHeapSort(); //从小到大排序,时间复杂度O(nlgn);
void MaxHeapSort(); //从大到小排序,时间复杂度O(nlgn);
//以下函数仅在最大堆下进行
void Insert(int k); //插入一个元素(最大堆)
void Delete(int i); //删除一个元素(最大堆)
Node Maximum(); //返回value最大的元素
Node ExtractMax(); //去掉并返回value最大的元素
//union two heap:union the vector of the two heaps, and call BuildMaxHeap()
int Size() {return heap.size();} //返回vector的元素个数
void PrintAll() {
for (auto i : heap)
cout << i.value << ends;
cout << endl;
}
}; void Heap::MaxHeapify(const int i) {
int largest;
if (Left(i) < heap_size && heap[Left(i)].value > heap[i].value)
largest = Left(i);
else
largest = i;
if (Right(i) < heap_size && heap[Right(i)].value > heap[largest].value)
largest = Right(i);
if (largest != i) {
swap(heap[i], heap[largest]);
MaxHeapify(largest);
}
} void Heap::MinHeapify(const int i) {
int least;
if (Left(i) < heap_size && heap[Left(i)].value < heap[i].value)
least = Left(i);
else
least = i;
if (Right(i) < heap_size && heap[Right(i)].value < heap[least].value)
least = Right(i);
if (least != i) {
swap(heap[i], heap[least]);
MinHeapify(least);
}
} void Heap::BuildMaxHeap() {
heap_size = heap.size();
for (int i = Parent(heap_size - ); i >= ; --i)
MaxHeapify(i);
} void Heap::BuildMinHeap() {
heap_size = heap.size();
for (int i = Parent(heap_size - ); i >= ; --i)
MinHeapify(i);
} void Heap::MinHeapSort() {
BuildMaxHeap();
for (int i = heap.size() - ; i > ; --i) {
swap(heap[i], heap[]);
--heap_size;
MaxHeapify();
}
} void Heap::MaxHeapSort() {
BuildMinHeap();
for (int i = heap.size() - ; i > ; --i) {
swap(heap[i], heap[]);
--heap_size;
MinHeapify();
}
} void Heap::Insert(int k) {
heap.push_back(INT_MIN);
IncreaseKey(heap.size() - , k);
} void Heap::Delete(int i) {
if (heap[heap.size() - ].value > heap[i].value) {
IncreaseKey(i, heap[heap.size() - ].value);
heap.pop_back();
} else {
heap[i] = heap[heap.size() - ];
heap.pop_back();
heap_size = heap.size();
MaxHeapify(i);
}
} Node Heap::Maximum() {
return heap[];
} Node Heap::ExtractMax() {
Node max = heap[];
heap[] = heap[heap.size() - ];
heap.pop_back();
MaxHeapify();
return max;
} void Heap::IncreaseKey(int i, int k) {
if (k <= heap[i].value)
return ;
while (i > && heap[Parent(i)].value < k) {
heap[i] = heap[Parent(i)];
i = Parent(i);
}
heap[i].value = k;
}

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. Android自定义View——彩色圆环统计图

      1.初始化变量 圆的粗细:圆环的大小. 标注:文字前面的圆点. 分配比例大小:由于需要计算圆环扫过的角度,计算方法使用:(比例/100)*360度,用百分比算出360度占用了多少,由于比例/100 ...

  2. MySQL授权用户登录访问指定数据库

    使用Navicat等客户端工具,选中需要共享的数据库,点击查询>新建查询 1.写SQL语句:GRANT ALL PRIVILEGES ON * TO 'test'@'%'IDENTIFIED B ...

  3. odoo 日志文件太大处理,logfile自动轮替

    可以在conf 文件中设置配置信息: logfile = /your/logfile/path/ logrotate = True ; 设置为True 即可自动更换旧的日志文件, 参考: https: ...

  4. iOS如何禁用长按页面弹出菜单

    iOS如何禁止用户长按页面导致弹出菜单? 给元素设置样式: -webkit-touch-callout:none; 补充:同样适用于图片如果想禁止用户保存或者复制等

  5. tensorflow之最近邻算法实现

    最近邻算法,最直接的理解就是,输入数据的特征与已有数据的特征一一进行比对,最靠近哪一个就将输入数据划分为那一个所属的类,当然,以此来统计k个最靠近特征中所属类别最多的类,那就变成了k近邻算法.本博客同 ...

  6. 10. react 基础 ref 的使用 及 React 16 的生命周期函数 及 生命周期函数使用场景

    一. ref 的使用 ( 直接获取 DOM 元素 ) 在 input 标签上 可以使用 ref 属性 获取当前DOM节点 eg: import React , { Component, Fragmen ...

  7. 三分钟入坑指北 🔜 Docsify + Serverless Framework 快速创建个人博客系统

    之前由于学摄影的关系,为了提高自己的审美,顺便锻炼下自己的英文能力,翻译了不少国外艺术类的 文章.最近一直想搭一个个人博客来存放这些内容,又懒得折腾建站,遂一直搁置. 直到偶然发现了 docsify ...

  8. Spring中的控制反转和依赖注入

    Spring中的控制反转和依赖注入 原文链接:https://www.cnblogs.com/xxzhuang/p/5948902.html 我们回顾一下计算机的发展史,从最初第一台计算机的占地面积达 ...

  9. ZOJ 1276 DP

    给出一系列的1x2的矩阵,要你求出矩阵以什么样的次序相乘才使得相乘次数最少,.(不用排序,只要决定该矩阵是和前面相乘比较好,还是后面). 今天仔细想了一下,跟之前做的DP题目做了下对比,你比如说猴子堆 ...

  10. jboss的JVMroute记录

    jboss5的nodename是在 /usr/local/jboss-5.1.0.GA/server/dms/deploy/jbossweb.sar/server.xml   这里的  jvmrout ...