用C++写二叉堆(优先队列)代码,详细注释-创新互联

 什么是二叉堆?

简单来说,二叉堆就是一颗完全二叉树,它具有特殊性质:

创新互联建站服务项目包括都昌网站建设、都昌网站制作、都昌网页制作以及都昌网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,都昌网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到都昌省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
  • 小顶堆:父节点的值小于两个孩子节点的值,处于堆顶的就是最小值

  • 大顶堆:父节点的值大于两个孩子节点的值,处于堆顶的就是大值

如下面两图就举出了小顶堆和大顶堆的例子

插入元素

插入元素会插入到最后一个元素的后面,不断地和父节点作比较,就拿小顶堆举例,如果当前节点的值小于父节点的值,就意味着当前节点要上浮,也就是交换当前节点和父节点的位置,下面就展示了插入1的上浮操作

删除堆顶元素

删除堆顶元素后,将最后一个节点放在根节点,再进行下滤操作,即找到合适的位置而满足二叉堆性质:

  • 对于小顶堆,首先比较两个子节点的值,找出值较小的子节点,再进行判断:

    • 如果该较小的子节点比当前节点的值还要大,则找到了合适的位置,或者当前节点的右节点大于堆的大小,下滤结束

    • 否则,将该较小的子节点与当前节点交换,重复之前操作

  • 对于大顶堆,首先比较两个子节点的值,找出值较大的子节点,再进行判断:

    • 如果该较大的子节点比当前节点的值还要小,则找到了合适的位置,或者当前节点的右节点大于堆的大小,下滤结束

    • 否则,将该较大的子节点与当前节点交换,重复之前操作

下面展示了删除堆顶元素2的过程

编写代码

使用的数组来表示二叉堆,第一个元素下标为1,左子树坐标为当前节点下标乘2,父节点下标为当前节点除2

#define ll(x) ((x)<<1)      //获得左子树下标 
#define p(x)  ((x)>>1)      //获得父节点下标

二叉堆用cnt表示下一个待插入元素的下标,等于当前元素个数加一,定义了compare函数,ab表示小顶堆

private:
    int cnt = 1, val[MAX];          
    //数组下标从1开始,cnt表示下一个元素将要插入的位置,当前元素个数为cnt-1 
    bool compare(int a, int b){return a:小顶堆

上浮代码如下,首先向val数组插入一个元素,cnt加一,并将新加入的元素不断上浮到合适位置

void push(int n){
    int idx = cnt;
    val[cnt++] = n;          
    while(idx >1){     //从最后一个元素cnt的位置插入,不断上浮到合适位置 
        if(compare(val[p(idx)], val[idx]))  swap(val[idx], val[p(idx)]);     
        idx = p(idx); 
    }
}

下滤代码如下,如果当前堆为空,则返回-1,先将堆顶元素和最后一个元素交换位置,然后将第一个元素不断下滤

int pop(){      //弹出堆顶元素 
    if(cnt == 1)    return -1;   
    int idx = 1, top = val[1];  //记录当前堆顶为top
    swap(val[1], val[--cnt]);   //将堆顶元素和最后一个元素交换位置,相当于删除了堆顶,cnt-1 
    while(idx<= cnt){      
        int child = ll(idx);
        //注意是child+1,大顶堆:和孩子节点较大者交换,小顶堆:和孩子节点较小者交换 
        if((child+1< cnt) && (compare(val[child], val[child+1])))  child++; 
        //这个条件很重要,不能删除 
        if(child< cnt && compare(val[idx], val[child]))    swap(val[child], val[idx]); 
        idx = child;
    }       
    return top;
}

完整代码如下:

#include#include
#define MAX 10000
#define ll(x) ((x)<<1)		//获得左子树下标 
#define p(x)  ((x)>>1)		//获得父节点下标 
using namespace std;
class Heap{	
private:
	int cnt = 1, val[MAX];			//数组下标从1开始,cnt表示下一个元素将要插入的位置,当前元素个数为cnt-1 
	bool compare(int a, int b){return a:小顶堆 
public:
	Heap(){}; 
	Heap(int array[], int n){for(int i=0; i1){		//从最后一个元素cnt的位置插入,不断上浮到合适位置 
			if(compare(val[p(idx)], val[idx]))	swap(val[idx], val[p(idx)]);	 
			idx = p(idx); 
		}
	}
	int pop(){		//弹出堆顶元素 
		if(cnt == 1)	return -1;	 
		int idx = 1, top = val[1];	//记录当前堆顶为top
		swap(val[1], val[--cnt]);	//将堆顶元素和最后一个元素交换位置,相当于删除了堆顶,cnt-1 
		while(idx<= cnt){		
			int child = ll(idx);
			if((child+1< cnt) && (compare(val[child], val[child+1])))	child++; //注意是child+1,大顶堆:和孩子节点较大者交换,小顶堆:和孩子节点较小者交换 
			if(child< cnt && compare(val[idx], val[child])) 	swap(val[child], val[idx]);	//这个条件很重要,不能删除 
			idx = child;
		}		
		return top;
	}
	int top()	{return val[1];}	//返回堆顶元素,但不弹出 
	int size()	{return cnt-1;} 
	void show() {for(int i=1;i

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧

文章名称:用C++写二叉堆(优先队列)代码,详细注释-创新互联
文章起源:https://www.cdcxhl.com/article22/ceeijc.html

成都网站建设公司_创新互联,为您提供品牌网站制作微信小程序做网站网站内链网站营销自适应网站

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联