时间复杂度:
建堆:O(n)
输出最小元素:O(1)
删除堆顶元素:O(logn)
注释版
#include<iostream>
using namespace std;
const int N=1e5+10;
int heap[N],siz;//siz=堆大小
void down(int index)
{
int min_index=index;
//堆索引为index的元素的左子儿子的索引为2*index
//若index的左子儿子存在 且 左子儿子的值比父节点的值小
//则令当前最小值索引min_index=左子儿子的索引=2*index
if(2*index<=siz && heap[2*index]<heap[min_index])
min_index=2*index;
//若index的右子儿子存在且右子儿子的值比堆中当前最小值索引的值小
//则令当前最小值索引min_index=右子儿子的索引=2*index+1
if(2*index+1<=siz && heap[2*index+1]<heap[min_index])
min_index=2*index+1;
if(index!=min_index)
{
swap(heap[index],heap[min_index]);
//递归继续处理min_index与其子儿子节点
down(min_index);
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
siz=n;
for(int i=1;i<=n;i++) scanf("%d",&heap[i]);
//树中最后一层不需要down操作
for(int i=n/2;i>0;i--) down(i);
while(m--)
{
printf("%d ",heap[1]);//堆顶元素为整个堆中元素的最小值
heap[1]=heap[siz];//除去堆顶元素
siz--;//更新堆大小
down(1);//更新堆
}
return 0;
}
无注释版
#include<iostream>
const int N=1e5+10;
using namespace std;
int s[N],siz;
void down(int i)
{
int index=i;
if(i*2<=siz && s[i*2]<s[index]) index=i*2;
if(i*2+1<=siz && s[i*2+1]<s[index]) index=i*2+1;
if(index!=i)
{
swap(s[index],s[i]);
down(index);
}
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>s[i];
siz=n;
for(int i=siz/2;i>=0;i--) down(i);
while(m--)
{
cout<<s[1]<<' ';
s[1]=s[siz];
siz--;
down(1);
}
}