理论基础
down 的操作就相当于每次找出
root root->left root->right
这三个元素中的最小值,如果不是root则进行交换。然后从新的位置递归进行 down 操作
代码实现
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 100010;
int h[N];
int n, m;
int numsize;
void down(int u)
{
int t = u; // 存储的最小元素的下标
if(u * 2 <= numsize && h[u * 2] < h[t]) t = u * 2; // 保证元素有左右儿子的情况下判断左儿子是否小于根节点的值
if(u * 2 + 1 <= numsize && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
if(u != t) // 如果当前最小值的位置不是根节点,那么进行元素交换并递归操作
{
swap(h[u], h[t]);
down(t);
}
}
int main()
{
scanf("%d%d",&n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]);
numsize = n;
for (int i = n / 2; i; i -- ) down(i); // O(n) 时间复杂度建立堆
while(m -- )
{
printf("%d ", h[1]);
h[1] = h[numsize];
numsize -- ;
down(1);
}
}