文章目录
- 二叉堆
- 概述
- 插入
- 代码
- 访问
- 代码
- 完整代码
- 优先队列:priority_queue
- 基本用法
- 小根堆的声明:
- 结构体
- 注意
- Thanks for reading!
二叉堆
概述
为什么不用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