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

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

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

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

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

代码如下:(仅供参考)

 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. CLR .net windows对win32 core抽象的新用处

    断断续续 花了一周的时间,把.net clr的一些知识看完了(确切的说是 一个段落),总体的感觉就是,ms把win32 core创建进程线程.虚拟地址.内存隔离的思想又重用了一遍,有所不同的是这次的场 ...

  2. 安装postgresql后找不到服务 postgresql service

    问题再现 环境: postgresql: 11.5 windows 10 企业版LTSC 64位 使用postgresql-11.5-1-windows-x64.exe安装后,让重新启动,但是重启后, ...

  3. idea 2019.3 最新破解补丁和激活码,可破解至2089年!

    链接:https://blog.csdn.net/qq_42914528/article/details/85617901 上面方法失效了,请尝试以下方式激活(2020.1.6更新) idea激活码( ...

  4. org.springframework.dao.CannotAcquireLockException异常分析

    错误信息如下: 2017-09-27 16:27:16.153 - [com.ldyun.base.service.impl.BaseRetailOrderServiceImpl] - 新增零售商品订 ...

  5. 2020.2.21一些python总结

    #字符串前面加r可以防止字符串转义 \也可以防止字符串转义#三引号可以实现输入多行文本#range(start,end,step)#列表 append添加一个元素到末尾 extend 添加一个素组到末 ...

  6. idea拉取git项目并创建为maven项目(新创建github项目)

    0 环境 系统环境:win10 编辑器:idea 1 正文 1 clone项目 跟着提示yes 下一步 2 在根节点添加pom.xml(maven) <?xml version="1. ...

  7. mysql比较运算,逻辑运算,范围查询,模糊查询

    比较运算 > < =  !=  <>   <=  >=  逻辑运算  and  or  not 范围查询  in   模糊查询  like             ...

  8. mysql的常见面试问题

    1.如何登陆mysql数据库 MySQL -u username -p 2.如何开启/关闭mysql服务 service mysql start/stop 3.查看mysql的状态 service m ...

  9. 洛谷P1257(暴力超时)

    1.先输入再求勾股定理会超时 2.需要一边输入一边求. #include<iostream> #include<cmath>#include<cstdio> usi ...

  10. python3 str.encode bytes.decode

    str.encode 把字符串编码成字节序列 bytes.decode 把字节序列解码成字符串 https://docs.python.org/3.5/library/stdtypes.html st ...