胡润研究院的调查显示,截至2017年底,中国个人资产超过1亿元的高净值人群达15万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。
输入格式:
输入首先给出两个正整数N(≤10^6)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。
输出格式:
在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。
输入样例:
8 3
8 12 7 3 20 9 5 18
输出样例:
20 18 12
代码:
#include<stdio.h>
#define MAXN 10
typedef int ElementType;
void Adjust(ElementType A[], int i, int N);//对A[]中前N个元素从第i个元素开始向下迁移调整
void InsertionSort(ElementType A[], int N);//插入排序
int main()
{
int N, M, i;
ElementType A[MAXN], temp;
scanf("%d%d",&N,&M);
if(N > MAXN){
for(i=0;i<M;i++)
scanf("%d",&A[i]);
for(i=(M-1)>>1;i>=0;i--)//前M个元素建立最小堆
Adjust(A, i, M);//只需维护一个规模为M的堆,之后元素若大于堆顶则加入,最后堆中一定是最大的M个元素
for(i=M;i<N;i++){
scanf("%d",&temp);//读入剩下的数据
if(temp>A[0]){//如果新数据比较大
A[0] = temp;//新数据替换最小元
Adjust(A, 0, M);//调整最小堆
}
}
for(i=M-1;i>0;i--){//对堆中M个数据进行堆排序
temp = A[0]; A[0] = A[i]; A[i] = temp;//将堆顶元素A[0]与当前堆的最后一个元素A[i]换位
Adjust(A, 0, i);//将有i个元素的新堆从根节点向下过滤调整
}
}else{//如果N很小则用插入排序
for(i=0;i<N;i++)
scanf("%d",&A[i]);
InsertionSort(A, N);
}
if(N < M) M = N;//如果N更小则输出前N个
printf("%d",A[0]);
for(i=1;i<M;i++)
printf(" %d",A[i]);
printf("\n");
return 0;
}
void Adjust(ElementType A[], int i, int N){
int Child;
ElementType temp;
for(temp=A[i];(2*i+1)<N;i=Child){
Child = 2*i + 1;//左孩子节点
if(Child!=N-1 && A[Child+1]<A[Child]) Child++;//Child指向左右孩子中较小者
if(temp>A[Child]) A[i] = A[Child];//若temp的孩子有比其小者,temp继续向下找位置
else break;
}
A[i] = temp;//将temp放到当前位置
}
void InsertionSort(ElementType A[], int N){
ElementType temp;
int i, j;
for(i=1;i<N;i++){
temp = A[i];//取出未排序序列中的第一个元素
for(j=i; j>0 && temp>A[j-1];j--)
A[j] = A[j-1];//依次与已排序序列中元素比较并右移
A[j] = temp;//放进合适位置
}
}