浅谈堆及其应用

\qquad 堆是一种树形数据结构,对于一个堆,其一定是一个完全二叉树而小根堆则额外满足左右子节点都大于父节点,大根堆则满足左右子节点都小于父节点,一般应用于求出某组数中的最大值或最小值(即根节点),本文主要介绍二叉堆其他堆我都不会

题目传送门

堆的性质

∙ \qquad\bullet 堆一定是一个完全二叉树(根据其定义)
∙ \qquad\bullet 堆中最大(最小)值即为根节点
∙ \qquad\bullet 每个堆的子树依然是一个堆

堆的操作

\quad 1.插入

假设你已经有了一个堆,如下
在这里插入图片描述
现在要将一个新节点0插入堆中
在这里插入图片描述
首先建立新节点储存0,然后将其与父节点比较,如果小于父节点则将其与父节点交换位置
在这里插入图片描述
哦吼,好像不太行
在这里插入图片描述
还是不行
在这里插入图片描述
舒服了
直到其变为根节点或者父节点小于它

void push(int k){
	heap[++ top] = k;
	int now = top;
	int fa = now >> 1;
	while((heap[fa] > heap[now]) && (now > 1)){
		swap(heap[fa],heap[now]);
		now = fa;
		fa = now >> 1;
	}
}

\quad 2.删除

插入完0后又觉得很不爽(一群正数里面混了个0 )又想把他删了,那怎么办呢?
先将其与叶节点交换,然后 t o p − − top -- top即可将其删除,再将交换后的节点与左右子节点比较,大于则交换下沉,重复此操作来维护堆的性质
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
完成啦

void del(){
	swap(heap[1],heap[top]);
	top --;
	int now = 1;
	while((now << 1) <= top){
		int son = now << 1;
		if((heap[son + 1] < heap[son]) && (son + 1 <= top)) son ++;
		if(heap[son] < heap[now]) swap(heap[son],heap[now]);
		else break;
		now = s;
	}
}

\quad 3.查询

直接输出堆顶就好

堆的STL实现

大人,时代变了
应该没人手写堆了吧 情怀党?
用优先队列实现堆,代码上完爆手写,速度上手写快一点,但是开了 O 2 O2 O2优化优先队列可能会快一点

#include<queue>				//优先队列头文件
priority_queue<int> q1;		//大根堆
priority_queue<int,vector<int>,greater<int> >q2;	//小根堆
q.top();		//取堆顶元素
q.pop();		//弹出堆顶元素
q.push();		//将某元素插入堆中
q.empty();		//判断堆是否为空,空返回1,否则返回0
q.size();		//查询堆内元素数量

在STL中使用优先队列经常会有到重载运算符
我会在另一篇博客中详解重载运算符

堆的复杂度

插入删除复杂度位 O ( log ⁡ 2 n ) O(\log_2n) O(log2n)

堆的应用

1.堆排序

正常建堆,一次弹出即可
但是裸的堆排序并没有什么用, s o r t sort sort比堆排序快而且写起来方便,大部分时候用到堆排序都是一些奇奇怪怪的操作

2.用2个堆维护查询第k小的操作

一个大根堆一个小根堆来维护 k k k小,并没有强制在线
用一个大根堆来存储 k − 1 k-1 k1个元素,当其元素为 k k k个时,弹出堆顶并将堆顶插入小根堆中,查询结果就是小根堆堆顶,以为 k − 1 k-1 k1小全在大根堆中

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值