n个元素求m个最大的元素:小顶堆的方法
1. 思路:先只建立一个含有m个元素的小顶堆;然后,利用小顶堆,对其它(n-m)个元素依次判断;最后得到一个m个最大元素的堆。
程序:
#include <iostream>
using namespace std;
void exchange(int &a,int &b)
{
int t=a;
a=b;
b=t;
}
int parent(int i)
{
return i>>1;
}
int left(int i)
{
return i<<1;
}
int rigth(int i)
{
return (i<<1)+1;
}
void min_heapify(int heapsize,int i, int a[])
{
int le=left(i);
int ri=rigth(i);
int minimum;
if (le<=heapsize && a[le]<a[i])
minimum = le;
else
minimum = i;
if (ri<=heapsize && a[ri]<a[minimum])
minimum = ri;
if (minimum!=i)
{
exchange(a[i],a[minimum]);
min_heapify(heapsize, minimum, a);
}
}
void build_min_heap(int m, int a[])
{
int i;
for (i=m/2;i>=1;i--)
min_heapify(m, i, a);
}
void heapsort(int a[], int n, int m){
build_min_heap(m, a);
for (int i=m+1;i<=n;i++) {
if(a[i]> a[1]) {
exchange(a[i], a[1]);
build_min_heap(m, a);
}
}
}
int main(int argc, char** argv) {
int n=20;//20 nubmers:
int m=8;//8 largest nubmers:
int a[n+1];
for (int i=1;i<=n;i++)
a[i] = rand()%99;
cout<<"n nubmers:"<<endl;
for (int i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
heapsort(a, n, m);
cout<<"m bigger nubmers:"<<endl;
for (int i=1;i<=m;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
程序中m=20, n=8时,输出为:
n nubmers:
65 54 29 86 84 69 34 75 8 46 27 50 57 92 51 95 93 75 83 8
m bigger nubmers:
75 83 75 86 84 93 95 92
2. 下面的程序是网上的一种错误做法,其思路是对所有的元素进行大顶堆排序,并依次取出m个最大元素。
#include <iostream>
#define MAXLENGTH 10001
using namespace std;
int a[MAXLENGTH];
int heapsize;
int m;
void exchange(int &a,int &b) {
int t=a; a=b; b=t;
}
int parent(int i) {
return i>>1;
}
int left(int i) {
return i<<1;
}
int rigth(int i) {
return (i<<1)+1;
}
void max_heapify(int i) {
int le=left(i);
int ri=rigth(i);
int largest;
if (le<=heapsize && a[le]>a[i])
largest = le;
else
largest = i;
if (ri<=heapsize && a[ri]>a[largest])
largest = ri;
if (largest!=i)
{
exchange(a[i],a[largest]);
max_heapify(largest);
}
}
void build_max_heap(int n)
{
int i;
heapsize=n;
for (i=n/2;i>=1;i--)
max_heapify(i);
}
void heapsort(int n)
{
int i;
build_max_heap(n);
cout<<a[1]; //大顶堆 第一个元素
m--;
for (i=n;i>=1;i--)
{
if (m==0)
break;
cout<<" ";
exchange(a[1],a[i]);
heapsize--;
max_heapify(1);
cout<<a[1];
m--;
}
}
int main(int argc, char** argv) {
int i,n;
cin>>n>>m;
for (i=1;i<=n;i++)
a[i]=rand()%99;
cout<<"n elements:"<<endl;
for (i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
cout<<"m largest elements:"<<endl;
heapsort(n);
return 0;
}
输入:
20 8
输出:
n elements:
65 54 29 86 84 69 34 75 8 46 27 50 57 92 51 95 93 75 83 8
m largest elements:
95 93 92 86 84 83 75 75
本文介绍了一种使用小顶堆高效找出数组中最大的m个数的方法。通过维护一个大小固定的小顶堆来逐步筛选出目标元素,避免了对全部元素进行排序带来的额外开销。

被折叠的 条评论
为什么被折叠?



