堆的c++实现
2018-03-22 21:24
197 查看
堆
堆,是一种完全二叉树。而且在这颗树中,父节点必然大于(对于小顶堆为小于)子节点。关于树的概念不了解可以看这里:http://blog.csdn.net/zhuyifan_jizhi/article/details/79645557而堆分为两种,最小堆和最大堆,这里主要是讲的最小堆。最小堆,是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于其左子节点和右子节点的值。现在我们知道了堆的概念,那么,如果我们要删除最小数并往堆里增加一个数,该怎么做呢?很显然最小的数就在堆顶,假设存储这个堆的数组是h的话,最小数就是好h[1]。接下来,我们将h[1]删除,将新增数放到堆顶。但加了新数以后,就不符合堆的特性了,所以我们需要将这个新数下调。向下调整时,我们需要将这个数与他的儿子中小的一个进行交换,直到符合堆的特性。下调代码如下://向下调整函数void siftdown(int i){//传入一个需要调整的节点编号
int t,flag=0;//flag用来标记是否需要向下调整
while(i*2<=n && flag==0){//当节点有儿子时,循环执行
if(h[i]>h[i*2]) t=i*2;//首先判断它与左儿子的关系,用t记录较小的节点编号
else t=i;
if(i*2+1<=n){//如果有右儿子,则对右儿子进行讨论
if(h[t]>h[i*2+1]) t=i*2+1;//如果右儿子更小,则更新t
}
if(t!=i){
swap(t,i);//交换函数要自己写
i=t;//准备继续向下调整
}
else{//说明i不需要调整了
flag=1;
}
}
return;
}说了半天,我们忽略了一个很重要的问题,那就是如何建立堆。
代码如下://建立堆的函数
void creat(){
int i;
for(int i=n/2;i>=1;i--)//从最后一个非叶节点到第一个节点依次调整
siftdown(i);
return;
} 堆有一个功能就是堆排序,时间复杂度是O(NlogN)。堆排序其实很简单,比如我们要从小到大排序,只需要先建立最小堆,然后每次删除堆顶元素并输出,直到堆为空为止。//寻找最小元素并删除
int deletemin(){
int t;
t=h[1];//用一个临时的变量记录顶点的值
h[1]=h
;//将堆的最后一个值赋值到堆顶
n--;//堆的元素减少1;
siftdown(1);//向下调整
return t;//返回之前记录的堆的顶点的最小值
}建堆及堆排序的完整代码如下:
#include<iostream> #include<cstdio> using namespace std; int h[101];//用来存放堆 int n; //交换函数 void swap(int x,int y){ int t; t=h[x]; h[x]=h[y]; h[y]=t; return; } //向下调整函数 void siftdown(int i){//传入一个需要调整的节点编号 int t,flag=0;//flag用来标记是否需要向下调整 while(i*2<=n && flag==0){//当节点有儿子时,循环执行 if(h[i]>h[i*2]) t=i*2;//首先判断它与左儿子的关系,用t记录较小的节点编号 else t=i; if(i*2+1<=n){//如果有右儿子,则对右儿子进行讨论 if(h[t]>h[i*2+1]) t=i*2+1;//如果右儿子更小,则更新t } if(t!=i){ swap(t,i);//交换函数要自己写 i=t;//准备继续向下调整 } else{//说明i不需要调整了 flag=1; } } return; } //建立堆的函数 void creat(){ int i; for(int i=n/2;i>=1;i--)//从最后一个非叶节点到第一个节点依次调整 siftdown(i); return; } //寻找最小元素并删除 int deletemin(){ int t; t=h[1];//用一个临时的变量记录顶点的值 h[1]=h ;//将堆的最后一个值赋值到堆顶 n--;//堆的元素减少1; siftdown(1);//向下调整 return t;//返回之前记录的堆的顶点的最小值 } int main(){ int num; cin>>num; for(int i=1;i<=num;i++) cin>>h[i]; n=num; creat();//建堆 for(int i=1;i<=num;i++) cout<<deletemin()<<" "; //删除顶部元素,其实也就是从小到大把数输出来 return 0; }
相关文章推荐
- 设计模式五(建造者模式,采用C++实现)
- C++实现的链表类实例
- 设计模式系列6-----C++实现状态模式(State Pattern)
- C++学习总结——vector容器的实现
- C++开发中一个解决方案里,两个项目的相互引用,相互依赖的实现方法(解决方法)
- 我所理解的设计模式(C++实现)——组合模式(Composite Pattern)
- 摩尔斯电码翻译(C++实现)
- BREW应用的c++实现注意点
- 设计模式C++实现(13)——中介者模式
- c++实现只有单个实例的类
- c++完美实现单例模式
- C++最大堆实现priority_queue优先级队列(算法导论)
- c++和java的内存管理,分别是怎么实现的,怎么防止内存泄露?
- matlab2c使用c++实现matlab函数系列教程-expstat函数
- k-means聚类算法C++实现
- 通讯录实现代码 C++ 链表
- c++实现二叉树(递归)
- 数组类(c++实现)
- 适用于实数范围的中缀表达式的 + - * / ( ) 计算(C++实现)
- 并查集类的c++封装,比較union_find algorithm四种实现方法之间的性能区别