前言:
- 堆是一种用于查找最大值/最小值的二叉树
- 支持添加/减少数据,添加/删除的复杂度是O(logn),查找的复杂度是O(1)
堆的结构:
- 大根堆:顾名思义,根结点的值比两个子结点都大.
- 小根堆:顾名思义,根节点的值比两个子结点都小.
- 堆中结点序号:若根节点序号为1,则根节点的左结点为2(1*2),右结点为3(1*2+1)。堆的全部结点均满足该性质.
堆的实现方式(具体见代码):
- 添加(add):增加一个结点,并将结点向上推,直到满足堆性质为止
- 删除根节点(del):将根结点的值设为堆中最后一个结点的值,并删除最后一个结点(删除最后一个结点不会影响堆的结构),再将根节点一直向下推,直到满足堆性质为止
- 删除任一结点(remove):原理同删除根结点,具体见代码
例题:https://www.luogu.org/problemnew/show/P3378
#include<cstdio>
#include<iostream>
using namespace std;
int heap[50001],n;
void up(int p){
while(p>1){
if(heap[p]<heap[p/2]){
swap(heap[p],heap[p/2]);
p=p/2;
}else break;
}
}
void add(int val){
heap[++n]=val;
up(n);
}
int getTop(){
return heap[1];
}
void down(int p){
int temp=p*2;
while(temp<=n){
if(heap[temp]>heap[temp+1])temp++;
if(heap[p]>heap[temp]){
swap(heap[p],heap[temp]);
p=temp,temp=p*2;
}else break;
}
}
void del(){
heap[1]=heap[n--];
down(1);
}
void remove(int p){
heap[p]=heap[n--];
up(p),down(p);
}
int main(){
int nn;
cin>>nn;
for(int i=1;i<=nn;i++){
int temp;
scanf("%d",&temp);
if(temp==1){
int addValue;
scanf("%d",&addValue);
add(addValue);
}else if(temp==2){
printf("%d\n",getTop());
}else if(temp==3){
del();
}
}
return 0;
}