二叉堆
概述
为什么不用pq呢
算比较简单的数据结构了
它可以用log的时间复杂度插入元素和访问(取出)最大(小)值(最大和最小只能取一个!)
缺点是除了干这个基本没有别的延伸用法。。。
主要性质(以大根堆为例,小根堆反过来就行):
1.是一棵二叉树(废话)
2.爸爸结点永远比儿子大(核心性质)
具体来看看代码实现吧~
插入
先把新元素放在队尾
只要没有到堆顶就不断尝试和爸爸交换;
如果比它的爸爸大,就可以交换
代码
void put(int k){
tree[++len]=son;//先放在队尾
int son=len;
while(son>1){//只要没有到堆顶就不断尝试和爸爸交换:如果比它的爸爸大,就交换
int fa=son>>1;
if(tree[fa]>tree[son]) return;//如果比爸爸小的话就可以结束交换了
swap(tree[fa],tree[son]);
son=fa;
}
return;
}
访问
先取出堆顶的最大值
把当前的队尾填到队首的位置
只要有儿子就不断尝试与儿子交换
如果比儿子中任何一个小,就与其交换
代码
int get(){
int res=tree[1];//先取出堆顶的最大值
tree[1]=tree[len--];//把当前的队尾填到队首的位置
int fa=1;
while(2*fa<=len){//只要有儿子就不断尝试与儿子交换:如果比儿子中任何一个小,就与其交换
int son=2*fa;
if(son<len&&tree[son]<tree[son+1]) son++;//找到较大的那个儿子
if(tree[son]<tree[fa]) break;
swap(tree[son],tree[fa]);
fa=son;
}
return res;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int N=1e5+100;
int tree[N];
int n,len;
int flag,x;
void put(int k){
tree[++len]=k;//先放在队尾
int son=len;
while(son>1){//只要没有到堆顶就不断尝试和爸爸交换:如果比它的爸爸大,就交换
int fa=son>>1;
if(tree[fa]>tree[son]) return;//如果比爸爸小的话就可以结束交换了
swap(tree[fa],tree[son]);
son=fa;
}
return;
}
int get(){
int res=tree[1];//先取出堆顶的最大值
tree[1]=tree[len--];//把当前的队尾填到队首的位置
int fa=1;
while(2*fa<=len){//只要有儿子就不断尝试与儿子交换:如果比儿子中任何一个小,就与其交换
int son=2*fa;
if(son<len&&tree[son]<tree[son+1]) son++;//找到较大的那个儿子
if(tree[son]<tree[fa]) break;
swap(tree[son],tree[fa]);
fa=son;
}
return res;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&flag);
if(flag==1){
scanf("%d",&x);put(x);
}
else printf("%d\n",get());
}
return 0;
}
优先队列:priority_queue
基本用法
priority_queue
需要头文件:queue
有这东西写什么二叉树啊
具体用法:
声明:priority_queue q;
插入元素:q.push(x);
访问堆顶:q.top();
弹出堆顶:q.pop();
以下是之前那段代码使用pq的版本:
int main(){
scanf("%d",&n);
priority_queue<int>q;
for(int i=1;i<=n;i++){
scanf("%d",&flag);
if(flag==1){
scanf("%d",&x);
q.push(x);
}
else{
printf("%d\n",q.top());
q.pop();
}
}
return 0;
}
简便程度不言而喻
小根堆的声明:
priority_queue<int,vector<int>,greater<int> (注意这里必须有个空格!)> q;
结构体
也可以用结构体,只是需要重载一下运算符 <:
struct node{
int value;
bool operator < (const node y)const{return value<y.value;};
};
int main(){
priority_queue<node>q;
int v;
node o;
q.push((node){v});//这里就是看个具体操作的用法,具体怎么操作看你需求啦~
o=q.front();q.pop();
return 0;
}
注意
1.当你已经pop完所有元素再取堆顶时,它会一直给你弹出的最后一个
2.而当你根本没push就直接访问top时,会直接RE