磁盘文件排序
问题描述:
输入:给定一个文件,里面最多含有n个不重复的正整数(也就是说可能含有少于n个不重复正整数),且其中每个数都小于等于n,n = 10^7。
输出:得到按从小到大升序排列的包含所有输入的整数的列表。
条件:最多有大约1MB的内存空间可用,但磁盘空间足够。且要求运行时间在五分钟以下,10秒为最佳结果。
分析:
首先注意的是它的内存要求,基本上否决了大多数的排序算法。
文件里面的数据是不重复的,这个很关键,因为下面的方案前提就是数据不重复。
位图方案
以位为最小单位,对应位为1,代表位数值,可以用20位长的字符串来表示一个所有元素都小于20的简单的非负数集合,边框用如下字符串来表示集合{1,2,3,5,8,13}:
01110100100001000000
对应位置则置1,没用对应数的位置则置0,开始扳手指头数数吧。我们可以采用一个具有1000万个位的字符串来表示这个文件,其中,当整数i在文件中时,第i位为1。
第一步,所有位置0,将集合初始化。
第二步,通过读入文件中的每个整数来建立集合,将对应的位都置1.
第三步,检验每一位,如果该位为1,就输出对应的整数。
这里不得不提一下c++库中的一个容器bitset,发现这个在处理位的时候简直牛,先来瞅瞅。
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
const int max = 20;
int arr[10] = {
2,9,3,5,4,0,18,11,12,15};
bitset<max> bit_map; //一种类模板,放入长度,定义了一个max位,每位都为0
bit_map.reset(); //所有位置0
int i;
for(i = 0;i< 10;i++)
{
bit_map.set(arr[i]); //将对应位置1
}
for(i = 0;i< max;i++)
{
if(bit_map.test(i)) //判断第i位,如果为1,返回true
cout << i << " ";
}
cout << endl;
return 0;
}
再加上文件操作,就是针对海量数据排序。
#include <iostream>
#include <bitset>
#include <assert.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
const int MAX = 5000000;
int main()
{
clock_t begin = clock();
bitset<MAX> bit_map;
bit_map.reset();
FILE * fp_unsort_file = fopen("data.txt","r");