Question
输入一个长度为 n
的整数数列,从小到大输出前 m
小的数。
输入格式
第一行包含整数 n
和 m
。
第二行包含 n
个整数,表示整数数列。
输出格式
共一行,包含 m
个整数,表示整数数列中前 m
小的数。
数据范围
1≤m≤n≤105
,
1≤数列中元素≤109
输入样例:
5 3
4 5 1 3 2
输出样例:
1 2 3
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e6 + 10;
int e[N], len; //e[N]用来存储完全二叉树结构,其中2x表示左孩子,2x+1表示右孩子
int n, m;
void down(int x)
{
int flag = x;
if (2 * x <= len && e[flag] > e[2 * x])flag = 2 * x; //和左右孩子比较
if (2 * x + 1 <= len && e[flag] > e[2 * x + 1])flag = 2 * x + 1;
if (flag != x) //如果发现指向父结点的移到孩子结点上就说明需要调换位置了
{
swap(e[flag], e[x]);
down(flag);
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> e[i];
}
len = n;
for (int i = n / 2; i; i--) //因为每次都是和这个结点的左右孩子比较,只需要从倒数第二层最后一个结点开始
down(i);
while (m--)
{
cout << e[1] << " "; //每次头结点都是最小的
e[1] = e[len]; //每输出一此头节点就删掉(有点像队列),并且将最后一个结点补上重新排
len--;
down(1);
}
return 0;
}
算法小白学习日记--堆排序