这个问题是从《编程珠玑》的开篇问题中看到的,问题大概是需要对一个存有近千万不重复的电话号码的文本进行排序,电话号码都为7位数。要求为10秒之内,使用内存1M左右。
位图法大概就是说建立一个很长的数组,然后开始读文件,每读到一个电话号码,就把这个电话号码数字为下标的数组对应位置记为1.完成之后,从0开始知道数组最后,如果值为1,则将下标输出到文件中。
自己根据书上提供的方法试了一下,发现没实现得了书上的1M内存,大概占11M左右,光那个位图数组就占了10M。主要原因是我这里用的字符来存储这个数字存不存在,一个字符占一个字节,8位。所以内存严重超出,本来想着使用位域等方法使得每个标记只占1位,最后没能实现,索性放弃了。
过程中还发现CFree貌似不支持建立10000000个元素的数组,会报错,所以把位图声明为指针,然后malloc 10000000 * sizeof(char)的内存。
在自己PC上测试,运行用时不超过5秒,占内存10M左右。
#include<iostream.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void sort();
void Generate();
int main(int argc, char *argv[])
{
//生成随机排序数字文件
//Generate();
//进行排序
sort();
return 0;
}
//读取文件内容,进行位图法存储,最后排序输出到文件
void sort()
{
FILE *p;
char *c;
c = (char*)malloc(sizeof(char) * 10000000);
int i = 0,num;
for(i = 0;i<10000000;i++)
{
c[i] = '0';
}
if((p = fopen("D:\\temp.txt","r+")) != NULL)
{
while( fscanf(p,"%d",&num) == 1 )
{
c[num] = '1';
}
rewind(p);
for(i = 0;i<10000000;i++)
{
if(c[i] == '1')
{
fprintf(p,"%d\n",i);
}
}
}
else
{
printf("File Error!\n");
}
}
//生成随机排列的不重复数字组成的文件
void Generate()
{
FILE *fp;
int *num;
num = (int*)malloc(sizeof(int) * 10000000);
int i = 0;
int rd;
int temp;
for(i=0;i<10000000;i++)
{
num[i] = i;
}
//根据随机数交换数组内容,实现所谓不重复乱序数组
srand((unsigned)time(NULL));
for(i=0;i<10000000;i++)
{
//这里有问题,默认的随机数范围是0到rand_max(0x7fff)
//所以下面的交换数组内容是在一定范围内的,不算整个数组的随机交换。暂时忽略
rd = rand()%(10000000-i) + i + 1;
temp = num[i];
num[i] = num[rd];
num[rd] = temp;
}
if((fp = fopen("D:\\temp.txt","w+")) != NULL)
{
for(i=0;i<10000000;i++)
{
fprintf(fp,"%d\n",num[i]);
}
}
else
{
printf("File Error!\n");
}
fclose(fp);
}