大致分析
在这个堆排序中 相对来说最不容易理解的应该是这里的这个 down操作以及for循环为什么从n/2开始了。
down操作其实就是当前节点分别同左,右节点相比 然后同最小的那个节点交换,这里为什么要同最小节点交换呢?
因为若不是寻找最小节点交换则可能会需要二次操作。
而for循环为什么从n/2开始呢,因为 n/2是最后一个可能拥有左右孩子节点的堆节点 而往后节点均没有孩子 所以从n/2开始
代码如下
//这里填你的代码^^
//注意代码要放在两组三个点之间,才可以正确显示代码高亮哦~
#include <iostream>
#include <algorithm>
using namespace std;
const int N =100010;
int h[N],cnt;//cnt为当前堆大小
int n ,m;
void down(int u){
int t = u;
if(u*2<=cnt&&h[u*2]<h[t])t=u*2;//前者判断左孩子是否存在 cnt为堆大小,后者与左孩子比较大小
if(u*2+1<=cnt&&h[u*2+1]<h[t])t=u*2+1;
if(u!=t){//若最小节点不是当前节点 则将最小节点与当前节点交换
swap(h[u],h[t]);
down(t);}
}
int main(){
scanf("%d%d",&n,&m);
for(int i =1;i<=n;i++)scanf("%d",&h[i]);
cnt = n;
for(int i =n/2;i;i--)down(i);//从最后可能拥有左右孩子的节点向上遍历。
while(m--){
printf("%d ",h[1]);//取堆顶
h[1]=h[cnt--];//将堆顶取出后将末尾元素调到堆顶然后size --(去尾)
down(1);
}
puts("");
return 0;
}