小根堆(Heap)的详细实现
堆的介绍
Heap是一种数据结构具有以下的特点:
1)完全二叉树
2)heap中存储的值是偏序
Min-heap: 父节点的值小于或等于子节点的值
Max-heap: 父节点的值大于或等于子节点的值

堆的存储
一般都用数组来表示堆,i结点的父结点下标就为(i–1)/2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。

由于堆存储在下标从0开始计数的数组中,因此,在堆中给定下标为i的结点时:
(1)如果i=0,结点i是根结点,无父结点;否则结点i的父结点为结点(i-1)/2;
(2)如果2i+1>n-1,则结点i无左子女;否则结点i的左子女为结点2i+1;
(3)如果2i+2>n-1,则结点i无右子女;否则结点i的右子女为结点2i+2。
堆的操作:小根堆插入元素
插入一个元素:新元素被加入到heap的末尾,然后更新树以恢复堆的次序。
每次插入都是将新数据放在数组最后。可以发现从这个新数据的父结点到根结点必然为一个有序的数列,现在的任务是将这个新数据插入到这个有序数据中——这就类似于直接插入排序中将一个数据并入到有序区间中。需要从下网上,与父节点的关键码进行比较,对调。

堆的操作:删除小根堆堆的最小元素
按定义,堆中每次都删除第0个数据。为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,堆的元素个数-1,然后再从根结点开始进行一次从上向下的调整。调整时先在左右儿子结点中找最小的,如果父结点比这个最小的子结点还小说明不需要调整了,反之将父结点和它交换后再考虑后面的结点。相当于从根结点将一个数据的“下沉”过程。

堆的操作:创建堆
对于叶子节点,不用调整次序,根据满二叉树的性质,叶子节点比内部节点的个数多1.所以i=n/2 -1 ,不用从n开始。就是从最后一个有叶子结点的结点开始。
堆排序
如果从小到大排序,创建大堆建好之后堆中第0个数据是堆中最大的数据。取出这个数据,放在数组最后一个元素上,将当前元素数-1,再执行下堆的删除操作。这样堆中第0个数据又是堆中最大的数据,重复上述步骤直至堆中只有一个数据时,数组元素就已经有序。
小根堆的实现
#include <iostream>
using namespace std;
const int DefaultSize = 50;
template<typename T>
class MinHeap
{
public:
//构造函数:建立空堆
MinHeap(int sz=DefaultSize)
{
maxHeapSize = (DefaultSize < sz) ? sz : DefaultSize;
heap = new T[maxHeapSize];
currentSize = 0;
}
//构造函数通过一个数组建立堆
MinHeap(T arr[],int n)
{
maxHeapSize = (DefaultSize < n) ? n : DefaultSize;
heap = new T[maxHeapSize];
for(int i=0;i<n;i++)
{
heap[i] = arr[i];
}
currentSize = n;
int currentPos = (currentSize - 2) / 2; //找最初调整位置:最后分支结点
while (currentPos>=0) //自底向上逐步扩大形成堆
{
siftDowm(currentPos, currentSize - 1); //局部自上向下下滑调整
currentPos--; //再向前换一个分支结点
}
}
//将x插入到最小堆中
bool Insert(const T& x)
{
if(currentSize==maxHeapSize)
{
cout << "Heap Full!" << endl;
return false;
}
heap[currentSize] = x; //插入
siftUp(currentSize); //向上调整
currentSize++; //堆计数+1
return true;
}
bool RemoveMin(T& x)
{
if(!currentSize)
{
cout << "Heap Empty!" << endl;
return false;
}
x = heap[0]; //返回最小元素
heap[0] = heap[currentSize - 1]; //最后元素填补到根结点
currentSize--;
siftDowm(0, currentSize - 1); //自上向下调整为堆
return true;
}
void output()
{
for(int i=0;i<currentSize;i++)
{
cout << heap[i] << " ";
}
cout << endl;
}
protected:
//最小堆的下滑调整算法
void siftDowm(int start, int end) //从start到end下滑调整成为最小堆
{
int cur = start;
int min_child = 2 * cur + 1; //先记max_child是cur的左子女位置
T temp = heap[cur];
while (min_child <=end)
{
if (min_child<end&&heap[min_child]>heap[min_child + 1]) //找到左右孩子中最小的一个
min_child++;
if(temp<=heap[min_child])
break;
else
{
heap[cur] = heap[min_child];
cur = min_child;
min_child = 2 * min_child + 1;
}
}
heap[cur] = temp;
}
//最小堆的上滑调整算法
void siftUp(int start) //从start到0上滑调整成为最小堆
{
int cur = start;
int parent = (cur - 1) / 2;
T temp = heap[cur];
while (cur>0)
{
if(heap[parent]<=temp)
break;
else
{
heap[cur] = heap[parent];
cur = parent;
parent = (parent - 1) / 2;
}
}
heap[cur] = temp; //回放temp中暂存的元素
}
private: //存放最小堆中元素的数组
T* heap;
int currentSize; //最小堆中当前元素个数
int maxHeapSize; //最小堆最多允许元素个数
};
//------------------------主函数-------------------------
int main(int argc, char* argv[])
{
MinHeap<int> h;
h.Insert(8);
h.Insert(5);
h.Insert(7);
h.Insert(9);
h.Insert(6);
h.Insert(12);
h.Insert(15);
h.output();
int out;
cout << static_cast<int> (h.RemoveMin(out)) << endl;
h.output();
int arr[10] = { 15,19,13,12,18,14,10,17,20,11 };
MinHeap<int> h1(arr,10);
h1.output();
}
小根堆(Heap)的详细实现的更多相关文章
- 05-树6. Path in a Heap (25) 小根堆
05-树6. Path in a Heap (25) Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.patest.cn/contes ...
- 基本数据结构——堆(Heap)的基本概念及其操作
基本数据结构――堆的基本概念及其操作 小广告:福建安溪一中在线评测系统 Online Judge 在我刚听到堆这个名词的时候,我认为它是一堆东西的集合... 但其实吧它是利用完全二叉树的结构来维护一组 ...
- scala写算法-用小根堆解决topK
topK问题是指从大量数据中获取最大(或最小)的k个数,比如从全校学生中寻找成绩最高的500名学生等等. 本问题可采用小根堆解决.思路是先把源数据中的前k个数放入堆中,然后构建堆,使其保持堆序(可以简 ...
- T-shirt buying CodeForces - 799B (小根堆+STL)
题目链接 思路: 由于题目说了只有1,2,3,三种色号的衣服,然后开三个对应色号的小根堆, 我是根据pair<int,int> 创建了一个以价格小的优先的优先队列. pair中的另外一个i ...
- 数据结构&堆&heap&priority_queue&实现
目录 什么是堆? 大根堆 小根堆 堆的操作 STL queue 什么是堆? 堆是一种数据结构,可以用来实现优先队列 大根堆 大根堆,顾名思义就是根节点最大.我们先用小根堆的建堆过程学习堆的思想. 小根 ...
- CJOJ 2482 【POI2000】促销活动(STL优先队列,大根堆,小根堆)
CJOJ 2482 [POI2000]促销活动(STL优先队列,大根堆,小根堆) Description 促销活动遵守以下规则: 一个消费者 -- 想参加促销活动的消费者,在账单下记下他自己所付的费用 ...
- poj2513 Fence Repair(小根堆)
Description Farmer John wants to repair a small length of the fence around the pasture. He measures ...
- 堆(heap)和栈(stack)几点认识
堆(heap)和栈(stack)主要的区别由以下几点:1.管理方式不同:2.空间大小不同:3.产生碎片不同:4.生长方向不同:5.分配归属不同:6.分配效率不同:7.存取效率不同:管理方式:对于栈来讲 ...
- (转)堆heap和栈stack
一 英文名称 堆和栈是C/C++编程中经常遇到的两个基本概念.先看一下它们的英文表示: 堆――heap 栈――stack 二 从数据结构和系统两个层次理解 在具体的C/C++编程框架中,这两个概念并不 ...
随机推荐
- Reg文件操作
注册表REG脚本文件测试 1.新建主键 例如,想在主键[HKEY_CURRENT_USER\Software]下新建一个名叫“新建主键名称”的主键. 可以打开记事本,写入如下内容: Windows R ...
- kvm虚拟化安装及虚拟机创建
1.开启虚拟化(VMware虚拟机为例),安装centos7操作系统. 2.查看CPU是否开启虚拟化 #zgrep "vmx" /proc/cpuinfo 3.配置yum源,通过 ...
- PC远程传文件到树莓派(PSCP详细版)
1.下载pscp软件 下载地址:http://www.pc6.com/softview/SoftView_456976.html 百度云下载地址:https://pan.baidu.com/s/1bZ ...
- webpack代理解决跨域
开了一个9000端口,又开了一个8881端口,在9000端口访问页面,数据接口是8881,这样就产生了跨域,如何解决? webpack中做如下配置: proxy: { '/api/*': { targ ...
- gulp常用插件之gulp-sourcemaps使用
更多gulp常用插件使用请访问:gulp常用插件汇总 gulp-sourcemaps这是一款用来生成映射文件的一个插件,SourceMap 文件记录了一个存储源代码与编译代码对应位置映射的信息文件.我 ...
- linux commands - 一次性解压多个tar.gz文件
tar -zxvf list所有tar.gz文件,然后利用xargs将其作为参数传给tar命令.-n 1表示每次传一个参数. xargs: https://www.cnblogs.com/wangqi ...
- MongoDB一些应用知识点
1.在生产环境中至少需要三个节点的复制集架构. 2.在多数的场景中WT引擎比MMAPv1更加出色. 3.要想达到极致的速度,那么一定要给MongoDB足够的内存. 4.避免使用短链接,充分利用连接池, ...
- 扩展BSGS求解离散对数问题
扩展BSGS用于求解axΞb mod(n) 同余方程中gcd(a,n)≠1的情况 基本思路,将原方程转化为a与n互质的情况后再套用普通的BSGS求解即可 const int maxint=((1< ...
- 《深入理解java虚拟机》读书笔记三——第四章
第四章 虚拟机性能监控与故障处理工具 1.JDK命令行工具 jps命令: 作用:列出正在运行的虚拟机进程. 格式:jps [option] [hostid] 选项:-q 只输出LVMID(Local ...
- rp算法 随机化 刷题记录
刷随机化是真的会上瘾quq 洛谷P3973 [TJOI2015]线性代数 看oiwiki上说可以随机化...于是... 就随机在a[i]上选一位取反,然后更新答案,最后输出答案. ...无话可说 代码 ...