什么是堆
注意:下标从1开始
堆的基本操作
down操作
void down(int i)
{
int t = i;
if(2*i <= cnt && heap[t] > heap[2*i])
t = 2*i;
if(2*i + 1 <= cnt && heap[t] > heap[2*i + 1])
t = 2*i + 1;
if(i != t)
{
swap(heap[i], heap[t]);
down(t);
}
}
up操作
void up(int i)
{
int u = i;
if(i/2 && heap[u] < heap[i/2])
u = i/2;
if(u != i)
{
swap(heap[u], heap[i]);
up(u);
}
}
堆的操作
1.插入一个数
heap[++cnt] = x; up(cnt);
2.求集合当中的最小值
heap[1];
3.删除最小值
heap[1] = heap[cnt--]; down(0);
4.删除任一元素
heap[k] = heap[cnt--]; up(k);down(k); //up和down操作只会执行一个
5.修改任一元素
heap[k] = x; down(k); up(k);
建堆
1.最底层都是叶子节点,共n/2个
2.从倒数第二层开始执行down操作:
for(int i = n/2; i>=1; i--) down(i);
题目
输入一个长度为 nn 的整数数列,从小到大输出前 mm 小的数。
输入格式
第一行包含整数 nn 和 mm。
第二行包含 nn 个整数,表示整数数列。
输出格式
共一行,包含 mm 个整数,表示整数数列中前 mm 小的数。
数据范围
1≤m≤n≤1051≤m≤n≤105,
1≤数列中元素≤1091≤数列中元素≤109
输入样例:
5 3
4 5 1 3 2
输出样例:
1 2 3
代码
#include <iostream>
using namespace std;
const int N =100010;
int heap[N];
void down(int i,int cnt)
{
int u = i;
if(2*i <= cnt && heap[u] > heap[2*i])
u = 2*i;
if(2*i + 1 <= cnt && heap[u] > heap[2*i+1])
u = 2*i+1;
if(u != i)
{
swap(heap[i], heap[u]);
down(u, cnt);
}
}
int main()
{
int n, m;
cin >> n >> m;
int cnt = n;
for(int i=1; i<=n; i++)
scanf("%d", &heap[i]);
for(int i=n/2; i>0; i--) down(i, cnt);
while(m--)
{
printf("%d ", heap[1]);
heap[1] = heap[cnt--];
down(1, cnt);
}
return 0;
}