问题描述:现在有上亿个浮点数,设计算法从中找到最大的10000个数据
解题思路:
1. 一般来说,这上亿个浮点数可以放在一个文本文件中,我们把这些数据进行分块处理,比如分为10块,每块数据量相对较少,可以装入内存
2. 将1000万个数据装入内存后,按照快速排序的方法从中查找最大的10000个数据,依次处理其余的9块,都找到每一块的最大的10000个数据
3. 将这10万数据合并,从中查找最大的10000个数据
该思路的核心算法就是从大量数据中利用快速排序查找出最大的若干个数据
算法如下:
/*
This is a free Program, You can modify or redistribute it under the terms of GNU
*Description:在大量数据中查找最大的若干个数据
*Language: C++
*Development Environment: VC6.0
*Author: Wangzhicheng
*E-mail: 2363702560@qq.com
*Date: 2012/10/31
*/
/*
*利用快速排序的方法进行查找,首先将整个待查找的数据放入STL中的向量中,然后依据快速排序的方法
递归查找
*/
#include <iostream>
#include <vector>
#include <Iterator>
#include <algorithm>
#include <ctime>
#include <fstream>
using namespace std;
const int N=100; //有100个数据
fstream fs;
template<class Iterator,class Type>
class SelectMaxN {
private:
int n; //选择多少个最大的数据
vector<Type>v; //将这些n个最大的数据保存在此向量中
Iterator Divide(Iterator start,Iterator finish) {
Type temp=*start;
while(start<finish) {
while(*finish>temp && finish>start) finish--;
if(finish>start) *start++=*finish;
while(*start<temp && finish>start) start++;
if(finish>start) *finish--=*start;
}
*start=temp;
return start;
}
void Solution(Iterator start,Iterator finish) {
Iterator mid=Divide(start,finish-1);
if(finish-mid==n) { //此时最大的n个元素已经生成
find(start,finish);
return;
}
else if(finish-mid>n) { //此时[mid,finish-1]区间中的数大于n
Solution(mid+1,finish);
}
else { //此时[mid,finish-1]区间中已经出现了最大的如干个数
int i=0; //用来计算从[mid,finish-1]区间中有多少个数
Iterator it=finish-1;
while(it>=mid) {
v.push_back(*it--);
i++;
}
n-=i; //需要在[start,mid-1]区间中查找n-i个最大的数
Solution(start,mid-1);
}
}
void find(Iterator start,Iterator finish) {
int i;
Iterator it=finish-1;
for(i=0;i<n && it>=start;i++) {
v.push_back(*it--);
}
}
public:
SelectMaxN(Iterator start,Iterator finish,int n) {
if(n>finish-start) this->n=finish-start; //n已经超过所有数据个数
this->n=n;
Solution(start,finish);
}
void show() {
vector<Type>::iterator it;
for(it=v.begin();it!=v.end();it++) {
fs<<*it<<endl;
}
}
};
void main() {
fs.open("e:\\log.txt");
if(!fs) {
cout<<"无法打开文件!"<<endl;
fs.clear();
fs.close();
return;
}
srand(unsigned(time(0)));
vector<int>a;
int i;
for(i=0;i<N;i++) { //随机生成N个整数
a.push_back(rand()%N);
fs<<"第"<<i<<"个数:"<<a[i]<<endl;
}
fs<<endl;
int n=10;
SelectMaxN<vector<int>::iterator,int>aa(a.begin(),a.end(),n);
fs<<"最大的"<<n<<"个数据是:"<<endl;
aa.show();
fs.clear();
fs.close();
}
测试:
日志文件内容是:
第0个数:17
第1个数:78
第2个数:81
第3个数:1
第4个数:80
第5个数:8
第6个数:70
第7个数:44
第8个数:98
第9个数:70
第10个数:39
第11个数:92
第12个数:64
第13个数:82
第14个数:60
第15个数:27
第16个数:28
第17个数:18
第18个数:87
第19个数:75
第20个数:45
第21个数:95
第22个数:10
第23个数:58
第24个数:8
第25个数:36
第26个数:32
第27个数:69
第28个数:67
第29个数:83
第30个数:60
第31个数:49
第32个数:55
第33个数:51
第34个数:71
第35个数:66
第36个数:59
第37个数:31
第38个数:95
第39个数:12
第40个数:37
第41个数:90
第42个数:95
第43个数:34
第44个数:72
第45个数:39
第46个数:57
第47个数:77
第48个数:13
第49个数:22
第50个数:93
第51个数:28
第52个数:62
第53个数:44
第54个数:64
第55个数:21
第56个数:14
第57个数:39
第58个数:97
第59个数:29
第60个数:10
第61个数:14
第62个数:43
第63个数:43
第64个数:83
第65个数:52
第66个数:36
第67个数:2
第68个数:29
第69个数:30
第70个数:76
第71个数:88
第72个数:79
第73个数:90
第74个数:37
第75个数:29
第76个数:85
第77个数:1
第78个数:93
第79个数:37
第80个数:11
第81个数:37
第82个数:72
第83个数:97
第84个数:90
第85个数:7
第86个数:35
第87个数:40
第88个数:23
第89个数:47
第90个数:57
第91个数:49
第92个数:14
第93个数:70
第94个数:86
第95个数:51
第96个数:97
第97个数:39
第98个数:22
第99个数:70
最大的10个数据是:
95
95
97
97
98
97
95
93
93
92