您的位置:首页 > 理论基础 > 数据结构算法

SDUT-3401 数据结构实验之排序四:寻找大富翁(堆排序)

2017-12-23 11:38 344 查看


数据结构实验之排序四:寻找大富翁

Time Limit: 200MS Memory Limit: 512KB

Submit Statistic


Problem Description

2015胡润全球财富榜调查显示,个人资产在1000万以上的高净值人群达到200万人,假设给出N个人的个人资产值,请你快速找出排前M位的大富翁。


Input

首先输入两个正整数N( N ≤ 10^6)和M(M ≤ 10),其中N为总人数,M为需要找出的大富翁数目,接下来给出N个人的个人资产,以万元为单位,个人资产数字为正整数,数字间以空格分隔。


Output

一行数据,按降序输出资产排前M位的大富翁的个人资产值,数字间以空格分隔,行末不得有多余空格。
 


Example Input

6 3
12 6 56 23 188 60



Example Output

188 60 56



Hint

请用堆排序完成。 


Author

xam

参考:https://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html

参考:http://blog.csdn.net/xiaoxiaoxuewen/article/details/7570621/

此题因为数组较大,使用高效排序依然可能超时,但因为M较小,所以由此入手,输入前M个数后,每次循坏找M个中最小的和新输入的

进行比较,若小于新输入的,则替换。

#include <bits/stdc++.h>///数组下标从0开始
using namespace std;
int a[12];
void adjust(int s,int e)///调整堆
{
int temp=a[s];
for(int i=s*2+1;i<=e;i*=2)/*为什么等于e:e不一定等于m,而且下面if有判断i<e,所以不用担心数组越界;i*=2:因为调整过后可能孩子堆被破坏,所以数组下标跳到孩子继续调整*/
{
if(i<e&&a[i]<a[i+1])///找到两个孩子中较大的
i++;
if(temp>a[i])///若大于两个孩子,则无需进行后面的判断,退出循环
break;
a[s]=a[i];
s=i;///完成一次调整后,堆顶变为i
}
a[s]=temp;///中途循坏退出,则再把调整前的堆顶记录插入到现在的堆顶
}

void Heap(int n)
{
for(int i=(n/2)-1; i>=0; i--)///依照从下到上的顺序构建堆,因为n/2之后的是叶子结点,所以无需调整
{
adjust(i,n);
}
for(int i=n-1; i>=1; i--)///共n个结点,所以调整n-1次
{
swap(a[0],a[i]);
adjust(0,i-1);
}
}

int main()
{
std::ios::sync_with_stdio(false);///防止超时
int n,m,x,k=0,l;
cin>>n>>m;
for(int i=1; i<=n; i++)
{
cin>>x;
if(k<m)
a[k++]=x;
else
{
l=0;
for(int j=1; j<m; j++)
{
if(a[l]>a[j])///记录m个数中的最小值
l=j;
}
if(a[l]<x)///若最小的小于x,就把他替换掉
a[l]=x;
}
}
Heap(m);///只对前m个构建堆
for(int i=m-1; i>=0; i--)
{
if(i==m-1)
cout<<a[i];
else
cout<<' '<<a[i];
}
cout<<endl;
return 0;
}


#include <bits/stdc++.h>///数组下标从1开始
using namespace std;
int a[100];
void adjust(int i,int n)///调整堆
{
int left=i*2;///左子树结点
int right=i*2+1;///右子树结点
int ma=i;
if(i<=n/2)///n/2之后的是叶子结点,无需调整
{
if(left<=n&&a[left]>a[ma])///找到三个点中的最大的
{
ma=left;
}
if(right<=n&&a[right]>a[ma])
{
ma=right;
}
if(ma!=i)///若左右子树的值大于根,就交换两者的值
{
swap(a[i],a[ma]);
adjust(ma,n);///若交换了值,则需要调整他们的孩子使孩子也是堆
}
}
}

void Heap(int n)
{
for(int i=(n/2); i>=1; i--)///依照从下到上的顺序构建堆,因为n/2之后的是叶子结点,所以无需调整
{
adjust(i,n);
}
for(int i=n; i>=2; i--)///共n个结点,所以调整n-1次
{
swap(a[1],a[i]);
adjust(1,i-1);
}
}

int main()
{
std::ios::sync_with_stdio(false);///防止超时
int n,m,x,k=1,l;
cin>>n>>m;
for(int i=1; i<=n; i++)
{
cin>>x;
if(k<m+1)
a[k++]=x;
else
{
l=1;
for(int j=2; j<k; j++)
{
if(a[l]>a[j])///记录m个数中的最小值
l=j;
}
if(a[l]<x)///若最小的小于x,就把他替换掉
a[l]=x;
}
}
Heap(m);///只对前m个构建堆
for(int i=m; i>=1; i--)
{
if(i==m)
cout<<a[i];
else
cout<<' '<<a[i];
}
cout<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: