问题:给出N个无序的数,选出其中最大的K个数。最简单的是将N个数进行排序,然后选出其中最大的K个数,但这种方法缺点是假如对上亿个数进行寻找K个最大的数,那么需要把上亿个数存入空间,然后排序,空间复杂度过大。
解决方法:采用堆序方法进行,思想:依次输入数,前K个数生成堆序,当输入K+1个数,将这个数与堆中的根结点进行比较,若比根节点大,则替换根结点,然后调用下滤函数percolatedown()调整堆序,使其满足堆的性质;若比根结点小不做任何操作,接着输入下一个数,重复上面的操作。由上可知,整个过程只需要能存储K个数的空间就行。
Heap.h
#pragma once
#include<iostream>
#include<vector>
using namespace std;
template<typename Comparable>
class Heap
{
public:
Heap(int num);
void insert(Comparable x);//用数组中k个数生成一个堆,
void percolatedown(); //调整替换后的堆
void show(); //输出最大的k个元素
private:
int k; //要寻找的最大的k个元素
int currsize;
vector<Comparable> arr;//存储k个元素的堆
};
Heap.cpp
#include"stdafx.h"
#include"Heap.h"
#include<iostream>
#include<vector>
using namespace std;
template<typename Comparable>
Heap<Comparable>::Heap(int num)
{
k=num;
currsize=1;
arr.resize(k+1);
}
template<typename Comparable>
void Heap<Comparable>::insert(Comparable x)
{
if(currsize<=k)
{
int hole=currsize;
for(;hole>=1&&arr[hole/2]>x;hole/=2)
arr[hole]=arr[hole/2];
arr[hole]=x;
currsize+=1;
}
else
{
if(x>arr[1])
{
arr[1]=x;
percolatedown();
}
}
}
template<typename Comparable>
void Heap<Comparable>::percolatedown()
{
int hole=1;
int child;
Comparable temp;
for(;2*hole<=k;hole=child)
{
child=2*hole;
if((child+1<=k)&&(arr[child+1]<arr[child])&&(arr[hole]>arr[child+1]))
{
++child;
temp=arr[hole];
arr[hole]=arr[child];
arr[child]=temp;
}
else if(arr[hole]>arr[child])
{
temp=arr[hole];
arr[hole]=arr[child];
arr[child]=temp;
}
else
return;
}
}
template<typename Comparable>
void Heap<Comparable>::show()
{
cout<<"最大的"<<k<<"个数为:"<<endl;
for(int i=1;i<=k;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
Beauty-2.5.cpp
// Beauty-2.5.cpp : 定义控制台应用程序的入口点。
//
//编程之美:寻找最大的k个数,采用堆方法查找最大的k个数。
#include "stdafx.h"
#include"Heap.h"
#include"Heap.cpp"
#include<iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int N;
int k;
cout<<"输入无序数的个数N:"<<endl;
cin>>N;
cout<<"找出最大数的个数:"<<endl;
cin>>k;
Heap<double> h(k);
double x;
cout<<"输入数据:"<<endl;
for(int i=0;i<N;++i)
{
cin>>x;
h.insert(x);
}
h.show();
return 0;
}