down operation
- Swap the current node with the smallest value in the child nodes
- If the node at this time is not the minimum number, continue this operation
// down操作
void down(int u)
{
int t = u;
// 看看有没有左儿子,如果存在则t等于左儿子
if (u * 2 <= s && h[u * 2] < h[t]) t = 2 * u;
if (u * 2 + 1 <= s && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
// t存的就是三个点里最小的节点编号
// 如果根节点不是最小编号,那么再重复一遍这个操作
if (u != t)
{
swap(h[u], h[t]);
down(t);
}
}
up operation
The up operation is relatively simple.
Each time it is compared with the parent node, if the parent node is larger than the current node, it is exchanged
// up操作
void up(int u)
{
// 1. 有父节点
// 2. 父节点比我当前这个节点要大
while (u / 2 && h[u / 2] > h[u])
{
swap(h[u / 2], h[u]);
u /= 2;
}
}
full code
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;
int h[N], s;
// down操作
void down(int u)
{
int t = u;
// 看看有没有左儿子,如果存在则t等于左儿子
if (u * 2 <= s && h[u * 2] < h[t]) t = 2 * u;
if (u * 2 + 1 <= s && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
// t存的就是三个点里最小的节点编号
// 如果根节点不是最小编号,那么再重复一遍这个操作
if (u != t)
{
swap(h[u], h[t]);
down(t);
}
}
int main()
{
scanf("%d%d", &n, &m);
// 数组编号应该从1开始
for (int i = 1; i <= n; ++i) scanf("%d", &h[i]);
s = n;
// 建堆 O(N)
for (int i = n / 2; i; --i) down(i);
// 输出堆顶并删除
while (m--)
{
printf("%d ", h[1]);
h[1] = h[s];
s--;
down(1);
}
puts("");
return 0;
}