7-18 寻找大富翁(25 分)
2015年胡润研究院的调查显示,截至2014年9月,个人资产在600万元以上高净值人群达290万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。
输入格式:
输入首先给出两个正整数N(≤106)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。
输出格式:
在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。
输入样例:
8 3
8 12 7 3 20 9 5 18
输出样例:
20 18 12 code:
#include <stdio.h> #include <string.h> int h[1000100]; int n,m; void swap(int x,int y){//交换两个值 int t; t = h[x]; h[x] = h[y]; h[y] = t; } //向下调整函数 void siftDown(int i){ int t,flag = 0;//t用来暂时保存较大的节点坐标,flag判断是否继续向下调整 while(i*2<=n&&flag==0){ if(h[i]<h[i*2]) t = i*2; else t = i; if(i*2+1<=n){//如果有右儿子,在进行比较 if(h[t]<h[i*2+1]){//这里要用h[t]比较,因为t是已经比较了的较大的 t = i*2+1; } } if(t!=i){//如果不相同需要交换 swap(i,t); i = t; } else//如果相同则说明不用继续调整 flag = 1; } } //建立堆 void creat(){ int i; for(i = n/2; i >= 1; i--){//从第一个非叶子节点开始一层一层向下调整 siftDown(i); } } //删除元素 int pop(){ int t = h[1];//保存h[1]作为返回值 h[1] = h[n];//把最后一个元素放在顶上进行调整 siftDown(1); n--;//开始忘了这句话,删除一个点后这个点的总数应该减少一个 return t; } int main(){ scanf("%d%d",&n,&m); int i; for(i = 1; i <= n; i++){ scanf("%d",&h[i]); } creat(); int flag = 0; if(m>n)m=n;//注意如果m比n大,只能输出n个 while(m--){ int rich; rich = pop(); if(flag!=0)printf(" "); printf("%d",rich); flag = 1; } return 0; }