输入一个长度为 n 的整数数列,从小到大输出前 m 小的数。
输入格式
第一行包含整数 n 和 m。
第二行包含 n 个整数,表示整数数列。
输出格式
共一行,包含 m 个整数,表示整数数列中前 m 小的数。
数据范围
1≤m≤n≤1e5
1≤数列中元素≤1e9
输入样例:
5 3
4 5 1 3 2
输出样例:
1 2 3
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N],n,m,r; //a[N]储存数组,r表示右边界
void down(int u)
{
int t=u;
if(2*u<=r&&a[2*u]<a[t]) //有左儿子并且左儿子比父节点小,进行交换
{
t=2*u;
}
if(2*u+1<=r&&a[2*u+1]<a[t]) //有右儿子并且右儿子比父节点小,进行交换
{
t=2*u+1;
}
if(t!=u) //说明进行了交换操作
{
swap(a[t],a[u]);
down(t); //再检测交换的点是否具有以上条件,没有则递归结束
}
}
int main()
{
cin>>n>>m;
r=n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
//从第一个非叶节点开始,从右到左,从下到上处理每个节点
for(int i=n/2;i>=1;i--)
{
down(i);
}
while(m--)
{
//堆顶保存的最小值,输出堆顶
cout<<a[1]<<" ";
//将堆顶和右边界交换
swap(a[1],a[r]);
//右边界左移
r--;
//重新处理堆顶
down(1);
}
}
优先队列模拟小根堆
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
priority_queue<int, vector<int>, greater<int>> q; //greater表示小的先输出
q.push(1);
q.push(8);
q.push(5);
while (!q.empty())
{
cout << q.top() << " ";
q.pop();
}
return 0;
}
输出结果: 1 5 8
优先队列模拟大根堆
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
priority_queue<int> q;
q.push(1);
q.push(8);
q.push(5);
while (!q.empty())
{
cout << q.top() << " ";
q.pop();
}
return 0;
}
输出结果:8 5 1