重点 堆的维护
拍桌!记得把循环的i从1开始!!!
(此处针对小根堆)每次将堆顶提出,即为当前最小值,再讲堆尾放到堆首,之后与左右节点比对,与其中较小的交换,直到重新成为小根堆。
附上父亲或儿子节点的计算方法:
用一个一维数组就可以装下一个完全二叉树,a[n]
的父亲为a[n/2]
,儿子是a[n*2],a[n*2+1]
。
#include<iostream>
#include<cstdio>
using namespace std;
int n,x;
int hp[20000],t,a[20000];
void push(int x) {
t++;
int now=t;
hp[now]=x;
while(now>1) {
if(hp[now]<hp[now/2]) {
int ls=hp[now];
hp[now]=hp[now/2];
hp[now/2]=ls;
now=now/2;
} else break;
}
}
int del() {
int res=hp[1];
hp[1]=hp[t];
t--;
int now=1;
while(2*now<=t) {
int tp=2*now;
if(tp<t && hp[tp]>hp[tp+1]) tp++;
if(hp[now]>hp[tp]) {
int ls=hp[now];
hp[now]=hp[tp];
hp[tp]=ls;
now=tp;
} else break;
}
return res;
}
int main() {
cin>>n;
for(int i=0; i<n; i++) {
cin>>x;
push(x);
}
for(int i=0;i<n;i++){
a[i]=del();
}
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
}