C++实现最小堆及插入,调整顺序,删除堆顶元素的操作
上次用Java实现了最大堆的封装,这次就来写一下最小堆的实现吧
插入函数的思路:
向堆中插入元素有两种情况,一种是堆为空,那么就让插入值作为根节点即可;另一种是堆不为空,那么此时就要进行判断当前节点与其父节点的大小关系比较。此时仍有两种情况,一种是当前节点大于父节点,这样正是我们所希望的;另一种是当前节点的值小于父节点,那么就要将二者的值进行调换,然后记得更新当前节点为原来父节点的位置,而父节点的位置同样需要更新(循环正常终止的时候说明已经到了根节点,此时最小值必定为根节点)
bool Insert(T data){
if(currentPos==MaxSize){
cout<<"Sorry , this heap is full!"<<endl;
return false;
}
currentPos++;
int targetPos=currentPos-1;
heap[targetPos]=data;
while(targetPos>0){
int parentPos=(targetPos-1)/2;
if(heap[parentPos]<heap[targetPos]){
break;
}else{
heap[targetPos]=heap[parentPos];
targetPos=parentPos;
}
}
return true;
}
//存在的bug是对根节点的大小比较,因为有可能targetPos=0而退出,此时就缺少了一次比较
siftDown调整过程思路:
给定要进行调整的节点的下标,我们只需要让它和它的两个子节点中最小的那个比较即可(前提是当前节点不是叶子节点),需要注意的是要先保存当前节点的值,比较之后按大小调整顺序即可。
void siftDown(int siftPos){
int siftPosition=siftPos;
T temp=heap[siftPosition];
int minChildPos=2*siftPosition+1;
while(minChildPos<currentPos){ //保证比较的条件成立
if((minChildPos<currentPos-1)&&(heap[minChildPos]>heap[minChildPos+1])){
minChildPos++;
}
if(temp<heap[minChildPos]){
break;
}else{
heap[siftPosition]=heap[minChildPos];
siftPosition=minChildPos;
minChildPos=2*siftPosition+1;
}
}
//作用:当要进行调换的位置不满足循环要求时,说明要进行调换的位置是叶子节点,那就不需要变换咯(这里也包括正常比较情况,可正常使用)
heap[siftPosition]=temp;
}
删除对顶元素
需要注意的是currentPos的大小要实时的进行更新,然后返回所删除的堆顶元素即可
T& deleteTop(){
if(currentPos<0){
cout<<"Sorry ,this heap is empty!"<<endl;
}
T target=heap[0];
heap[0]=heap[currentPos-1];
currentPos--;
siftDown(0);
return target;
}
下面是完整的C++关于最小堆的实现的代码
#include <iostream>
using namespace std;
template<class T>
class MinHeap{
T *heap;
int MaxSize;
int currentPos;
public:
MinHeap(int MS){
heap=new T[MS];
currentPos=0;
MaxSize=MS;
}
bool Insert(T data){
if(currentPos==MaxSize){
cout<<"Sorry , this heap is full!"<<endl;
return false;
}
currentPos++;
int targetPos=currentPos-1;
heap[targetPos]=data;
while(targetPos>0){
int parentPos=(targetPos-1)/2;
if(heap[parentPos]<heap[targetPos]){
break;
}else{
heap[targetPos]=heap[parentPos];
targetPos=parentPos;
}
}
return true;
}
void siftDown(int siftPos){
int siftPosition=siftPos;
T temp=heap[siftPosition];
int minChildPos=2*siftPosition+1;
while(minChildPos<currentPos){ //保证比较的条件成立
if((minChildPos<currentPos-1)&&(heap[minChildPos]>heap[minChildPos+1])){
minChildPos++;
}
if(temp<heap[minChildPos]){
break;
}else{
heap[siftPosition]=heap[minChildPos];
siftPosition=minChildPos;
minChildPos=2*siftPosition+1;
}
}
//作用:当要进行调换的位置不满足循环要求时,说明要进行调换的位置是叶子节点,那就不需要变换咯
heap[siftPosition]=temp;
////////////////////////////////////////////
}
T& deleteTop(){
if(currentPos<0){
cout<<"Sorry ,this heap is empty!"<<endl;
}
T target=heap[0];
heap[0]=heap[currentPos-1];
currentPos--;
siftDown(0);
return target;
}
};
int main()
{
cout << "Hello world!" << endl;
MinHeap<int> minHeap(7);
minHeap.Insert(1);
minHeap.Insert(2);
minHeap.Insert(4);
minHeap.Insert(3);
minHeap.Insert(6);
minHeap.Insert(7);
minHeap.Insert(5);
for(int i=1;i<=7;i++){
cout<<minHeap.deleteTop()<<endl;
}
return 0;
}
程序运行结果如下
总结:
代码中存在一定得错误,出在 Insert函数中。个人认为需要对targetPos为0的特殊情况再加一层判断,估计就能解决。但是对正常添加元素还是能得到比较正常的结果的。
C++实现最小堆及插入,调整顺序,删除堆顶元素的操作的更多相关文章
- Java实现堆的封装,进行插入,调整,删除堆顶以完成堆排序实例
简介 堆对于排序算法是一个比较常用的数据结构,下面我就使用Java语言来实现这一算法 首先,我们需要知道堆的数据结构的形式,其实就是一个特殊的二叉树.但是这个二叉树有一定的特点,除了是完全二叉树以外, ...
- 笔试算法题(46):简介 - 二叉堆 & 二项树 & 二项堆 & 斐波那契堆
二叉堆(Binary Heap) 二叉堆是完全二叉树(或者近似完全二叉树):其满足堆的特性:父节点的值>=(<=)任何一个子节点的键值,并且每个左子树或者右子树都是一 个二叉堆(最小堆或者 ...
- PTA 最小堆插入元素和删除堆顶(无哨兵元素) (20分)
PTA 最小堆插入元素和删除堆顶(无哨兵元素) (20分) 对于给定的最小堆(优先队列),分别实现插入元素和删除堆顶的函数. 函数接口定义: int insertIntoHeap(struct Hea ...
- 堆+建堆、插入、删除、排序+java实现
package testpackage; import java.util.Arrays; public class Heap { //建立大顶堆 public static void buildMa ...
- Kafka集群优化篇-调整broker的堆内存(heap)案例实操
Kafka集群优化篇-调整broker的堆内存(heap)案例实操 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查看kafka集群的broker的堆内存使用情况 1>. ...
- 设顺序表中的数据元素递增有序,试着写一算法,将x插入到顺序表上的适当位置上,以保持该表的有序性。
原创,转载请注明出处.https://www.cnblogs.com/yangf428/p/11254370.html 天勤例题[2-1]: 设顺序表va中的数据元素递增有序.试写一算法,将x插入到顺 ...
- 堆实战(动态数据流求top k大元素,动态数据流求中位数)
动态数据集合中求top k大元素 第1大,第2大 ...第k大 k是这群体里最小的 所以要建立个小顶堆 只需要维护一个大小为k的小顶堆 即可 当来的元素(newCome)> 堆顶元素(small ...
- Java中数组的几个常用算法:插入算法,删除算法,冒泡排序算法
前言: 在Java中我们常常会用数组,提到数组就不得不介绍数组中常用到的几个算法. 有插入算法,删除算法,冒泡排序算法等. 在学习这几个数组的算法前,我们先来了解一下关于数组一些基本知识. 数组的基本 ...
- 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp
题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...
随机推荐
- Eclipse 一直不停 building workspace完美解决总结
一.产生这个问题的原因多种1.自动升级 2.未正确关闭 3.maven下载lib挂起 等.. 二.解决总结(1).解决方法 方法1.修改eclipse启动文件 eclipse.ini ...
- linux上快速搭建宝塔面板来操作便捷功能
关于宝塔 Linux版请确保纯净系统安装(支持CentOS.Ubuntu.Debian.Fedora.Deepin),Web端管理,QQ群及论坛技术支持一键LAMP/LNMP.创建网站FTP.数据库. ...
- android基础-界面开发注意事项
做安卓开发时一定要注意,主线程不能更改UI界面,如果出现程序运行时崩溃的情况,如果没有明显的语法错误,请检查自己的进程是否出现冲突,崩溃.如果有与后台的连接,即请求向服务器发送请求的时尤其需要注意,或 ...
- Centos 7安装MYSQL
1.下载RPM源 直接使用yum命令下载mysql来进行安装是不能成功的,安装过程会有问题,这里需要使用rpm命令来先进下载.下载路径为: http://dev.mysql.com/get/mysql ...
- CRM客户关系管理系统(五)
第五章.分页功能开发 5.1.修改BaseKingAdmin和完善前段页面显示 现在访问没有注册的model会报错,因为基类中没有写list_display和list_filter. 在基类中设置一个 ...
- Django项目实战之用户头像上传与访问
1 将文件保存到服务器本地 upload.html <!DOCTYPE html> <html lang="en"> <head> < ...
- 通讯协议序列化解读(一) Protobuf详解教程
前言:说到JSON可能大家很熟悉,是目前应用最广泛的一种序列化格式,它使用起来简单方便,而且拥有超高的可读性.但是在越来越多的应用场景里,JSON冗长的缺点导致它并不是一种最优的选择. 一.常用序列化 ...
- Node.js 全局对象介绍
全局对象 这些对象在所有模块里都可用.有些对象不是在全局作用域而是在模块作用域里,这些情况下面文档都会标注出来. global {Object} 全局命名空间对象. 浏览器里,全局作用域就是顶级域.如 ...
- 实验与作业(Python)-04 数据类型、数学函数与字符串
截止日期 实验目标 继续熟悉for循环与turtle 数值运算符 math库常用函数 字符串转化为数值类型(int, float, complex) 字符串常用函数 实验内容 任务1.使用for代替w ...
- Eric5 for Python 3.3.3安装指南
一言蔽之,搭配是关键.以32位Window为例,先后安装: 1.PyQt PyQt4-4.10.3-gpl-Py3.3-Qt4.8.5-x32.exe http://www.riverbankcomp ...