手写一个二叉堆

二叉堆就是利用了二叉树的结构进行维护。

a.插入

插入一个数就是把当前数 x x x放到二叉树的尾部,然后沿着父边进行不断比较,如果比父亲大就更换,然后重复,否则退出。

void add(int x){
a[++cnt] = x;
int u = cnt;
while(u>1){
int fa = u>>1;
if(a[u]>=a[fa]) return;
swap(a[u],a[fa]);
u = fa;
}
}

b.删除

把尾部元素与首部元素交换,然后个数减一。

再沿着较小的儿子边进行更新。

如果比儿子大就更新,重复,否则就退出。

void del(){
if(cnt<1) return;
a[1] = a[cnt--];
int u = 1;
while((u<<1)<=cnt){
int v = u<<1;
if(v<cnt && a[v+1]<a[v]) v++;
if(a[u]<=a[v]) return;
swap(a[u],a[v]);
u=v;
}
}

c.获取堆顶

就是第一个元素,也就是二叉树的根

int get(){
return a[1];
}

d.总代码

// Problem: P3378 【模板】堆
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3378
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// Date: 2022-03-02 10:40:24
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e6+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = {402653189,805306457,1610612741,998244353};
#define mst(a,b) memset(a,b,sizeof a)
#define db double
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
template <typename T> //x=max(x,y) x=min(x,y)
void cmx(T &x,T y){
if(x<y) x=y;
}
template <typename T>
void cmn(T &x,T y){
if(x>y) x=y;
}
int a[N],cnt;
void add(int x){
a[++cnt] = x;
int u = cnt;
while(u>1){
int fa = u>>1;
if(a[u]>=a[fa]) return;
swap(a[u],a[fa]);
u = fa;
}
}
void del(){
if(cnt<1) return;
a[1] = a[cnt--];
int u = 1;
while((u<<1)<=cnt){
int v = u<<1;
if(v<cnt && a[v+1]<a[v]) v++;
if(a[u]<=a[v]) return;
swap(a[u],a[v]);
u=v;
}
}
int get(){
return a[1];
}
int main(){
int n;
scanf("%d",&n);
while(n--){
int op,x;
scanf("%d",&op);
if(op==1){
scanf("%d",&x);
add(x);
}
else if(op==2){
printf("%d\n",get());
}
else del();
}
return 0;
}