结合数据结构一起看,理解得更为清晰一些。
需要反复记忆,理解
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int h[N];
int n,m;
int si,cnt;
void down(int u){
int t = u;
//判断u是否存在左右儿子,并且比较值的大小
if(2*u <= si && h[2*u] < h[t]) t = 2 * u;
if(2 * u + 1 <= si && h[2 * u + 1] < h[t]) t = 2 * u + 1;
if(t != u){//当下标不同时,
swap(h[t],h[u]);
down(t);
}
}
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> h[i];
si = n;
for(int i = n/2; i; i--) down(i);//进行建堆。对根节点到n/2这些结点进行下滤。使用的是物理(向量数组)的下标,相当于结点的秩
while(m--){
cout << h[1] <<' ';
h[1] = h[si];
si--;
down(1);//因为删除了最小值(堆顶),将堆底最后一个元素(值大)放于堆顶,需要进行下滤
}
return 0;
}