#include <stdio.h> #include <stdlib.h> #include <string.h> void Swap(int a[], int i, int j) // 交换函数 { int t = a[i]; a[i] = a[j]; a[j] = t; } void HeapMerge(int *a,int i,int n) //调整函数,也是核心地方 // 如下的树的概念都是把这个堆转变成树来讲的 { int lc = 2*i; // 由于咱们用一位数组存放的,这里下标从1开始,若是1存放根结点,那么左紫薯就是2×i 右紫薯是 2 × 1 + 1 int rc = 2*i+1; // 由于堆排序这里是一颗彻底二叉树,层次遍历这个树,而后依次放进这个下标从1开始的数组中,获得的就是以上结果了 int k = i; //存放当前调整的结点的下标 if(i <= n/2) //若是大于n/2,就是叶子结点了,就不须要再调整了 { if(lc <= n && a[lc] > a[k]) // 左子树的比较 { k = lc; } if(rc <= n && a[rc] > a[k]) // 右紫薯的比较 这样子就是选的左右紫薯中大的那个了 { k = rc; } if(k != i) // 若是找到了它的左右紫薯中比它大的 { Swap(a,i,k); // 交换这两个值 HeapMerge(a,k,n); // 继续把k这个位置的数,也就是上一步中为交换前的a[i],往下调整,要保证左右紫薯都小于根节点 } } } void HeapCreat(int *a,int n) { for(int i=n/2; i>=1; i--) { HeapMerge(a,i,n); // 从第一个非叶子结点开始调整树,n/2就是第一个非叶子结点,彻底二叉树的性质决定的。 } } void HeapSort(int *a,int n) { int i; HeapCreat(a,n); //先调整好树,让成为一个大顶堆 for(i=n; i>=1; i--) { Swap(a,1,i); // 把这个堆顶,也就是最大的,放到最后 HeapMerge(a,1,i-1); // i - 1 也就是剩下的再从新调整 // 直到所有完成,层次遍历树变成有序序列,对应的数组就是有序数组 } } int main() { int n,m,p,t, Min; while(scanf("%d %d",&n,&m)!=EOF) { int a[12]; p = 1; for(int i = 0; i < n; i++) // 这个题的缘由,不能所有输入,对于所有的数建堆 { scanf("%d",&t); if(p < m + 1) a[p++]=t; else { Min = 1; for(int j = 2; j < p; j++) { if(a[Min] > a[j]) Min = j; } if(a[Min] < t) a[Min] = t; } } //挑出来前 m 大的数 HeapSort(a,m); // 堆排 for(int i = m; i >= 1; i--) if(i==m) printf("%d",a[i]); else printf(" %d",a[i]); printf("\n"); } return 0; }