优先队列和二叉堆
优先队列是一种常用的ADT,其中的元素有序排列,入队的元素会插入到正确的位置,队首元素始终为最小(大)值,队首出队后优先队列仍然保持原来的性质。
这里我们规定优先队列以升序排列。
优先队列提供的接口包括:
- insert 插入元素
- top 得到队首元素
- pop 删除队首元素
二叉堆是优先队列一种常用的实现,二叉堆是一种完全二叉树,完全二叉树除最低一层外其它层均被填满,最低一层的节点全部集中在左侧。完全二叉树的性质决定它可以很容易地由二叉数组来实现。
二叉堆满足堆序性,即任意一个节点X的父节点不大于X(最小堆)。由堆序性可知,二叉堆的根节点一定为最小值或最大值,根节点为最小值的堆称为最小堆,根节点为最大值的堆称为最大堆。
最小堆类的声明:
template<typename val_t>
class MinHeap {
protected:
const static size_t capcity = 10000;
size_t size;
val_t vec[capcity];
public:
MinHeap();
void insert(val_t val);
bool empty();
void rmMin();
val_t getMin() {
return vec[1];
};
~MinHeap() = default;
};
插入元素#
插入元素采用上滤的方法:
(1)在数组超出末端(size位置)创建一个空穴
(2)比较新元素与空穴父节点的大小,若新元素较大则将原父节点填入空穴,原父节点的位置变为空穴
(3)直至新元素不大于空穴父节点时停止空穴上溯
template<typename val_t>
void MinHeap<val_t>::insert(val_t val) {
size_t i;
for (i = ++size; vec[i/2] > val; i /= 2) {
vec[i] = vec[i / 2];
}
vec[i] = val;
}
在实现过程中,我们只是用i标记了空穴的位置,并没有交换空穴与父节点的位置。
删除根元素#
删除元素采用恰好相反的下滤策略:
(1) 移除根节点后在根节点处产生了一个空穴
(2) 比较空穴的左右子节点,较大的一个与空穴交换位置,直至空穴到达最下层
(3) 将原来最后一个元素填入空穴的位置
template<typename val_t>
void MinHeap<val_t>::rmMin() {
size_t i, next;
val_t min, last;
if (empty()) {
return;
}
min = vec[1];
last = vec[size--];
for (i = 1; i * 2 <= size; i = next) {
//find smaller next
next = i * 2;
if (next != size && vec[next + 1] < vec[next]) {
next++;
}
//
if (last > vec[next]) {
vec[i] = vec[next];
}
else {
break;
}
}
vec[i] = last;
}
一言不发就丢代码:#
#include <iostream>
//#include <vector>
using namespace std;
template<typename val_t>
class MinHeap {
protected:
const static size_t capcity = 10000;
size_t size;
val_t vec[capcity];
public:
MinHeap();
void insert(val_t val);
bool empty();
void rmMin();
val_t getMin() {
return vec[1];
};
~MinHeap() = default;
};
template<typename val_t>
MinHeap<val_t>::MinHeap() {
size = 0;
}
template<typename val_t>
bool MinHeap<val_t>::empty() {
if (size) {
return false;
}
else {
return true;
}
}
template<typename val_t>
void MinHeap<val_t>::insert(val_t val) {
size_t i;
for (i = ++size; vec[i/2] > val; i /= 2) { //covert > to <, to get a max heap
vec[i] = vec[i / 2];
}
vec[i] = val;
}
template<typename val_t>
void MinHeap<val_t>::rmMin() {
size_t i, next;
val_t min, last;
if (empty()) {
return;
}
min = vec[1];
last = vec[size--];
for (i = 1; i * 2 <= size; i = next) {
//find smaller next
next = i * 2;
if (next != size && vec[next + 1] < vec[next]) {
next++;
}
//
if (last > vec[next]) {
vec[i] = vec[next];
}
else {
break;
}
}
vec[i] = last;
}
作者:finley
出处:https://www.cnblogs.com/Finley/p/5469206.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!