2.5亿个整数中找出不重复的数代码实现
2014-03-18 20:10
120 查看
对于在2.5亿个整数中找出不重复的数(内存不足以容纳这2.5亿个整数),已经有众多前辈给出了比较详尽的算法描述,但在具体实现上现有的例子则比较简单,规模偏小。昨天生成2.5亿个数之后,开始读文件统计,结果10个小时左右没出结果。所以今天用25万个数做实验,几分钟就得出了统计结果。在VS2010环境里新建C++控制台工程,完整的实现代码如下。程序算法实现部分参考http://blog.csdn.net/leeboy_wang/article/details/8980682,在此向转载者和原作者表示衷心谢意。
//题目要求:在2.5亿个整数中找出不重复的整数,内存不足以容纳这2.5亿个整数。 //采用2-Bitmap方法,2bit标识一个数字状态,00表示未出现过,01表示出现1次,10表出现两次或更多 #include"StdAfx.h" #include<stdlib.h> #include<string.h> #include<memory.h> //2.5亿个整数所需存储空间为2.5*10^8*4=10^9 Byte=976562.5KB=953.6743MB<1G //num=rand();用来生成随机数,每次都生成一个介于0-RAND_MAX范围内的数。 //RAND_MAX=32767 //用char数组存储2-Bitmap,不用考虑大小端内存的问题 //2^15=32768,用两个bit标识一个随机数的状态,共需要2^16bit=2^13Bytes=8192Byte //char数组的大小不低于8192,这里定义为8200 unsigned char flags[8200]; //数组大小自定义 //获取数字出现的次数,参数为要查看的数字,首先计算该数字的两个标识位所在的位置,由i,j确定 unsigned get_val(int idx) { int i = idx/4; int j = idx%4; unsigned ret = (flags[i]&(0x3<<(2*j)))>>(2*j); return ret; } //标识位的置位函数,参数为遍历时对应的数字idx,val对应的是该数字的出现次数,第一次出现就为1 unsigned set_val(int idx, unsigned int val) { int i = idx/4; int j = idx%4; unsigned tmp = (flags[i]&~((0x3<<(2*j))&0xff)) | (((val%4)<<(2*j))&0xff); flags[i] = tmp; return 0; } //对遍历到的每个数字要执行的操作 //首先根据数字值获得该数字出现的次数,如果>=2次就不执行任何操作,返回。 //如果数字出现过0次或1次,就在该数字对应的标识位上加1. unsigned add_one(int idx) { if (get_val(idx)>=2) { return 1; } else { set_val(idx, get_val(idx)+1); return 0; } } //生成2.5亿个随机数的函数 void CreateNumFiles() { int i,j,k;//标识三重循环,生成2.5亿个数 int randnumber;//存储生成的随机数 FILE *fp; char str[10];//存储序号,用于生成文本文件的命名 char ext[5]=".txt";//存储文本文件的扩展名 for(i=0;i<2500;i++) { sprintf(str,"%d",i+1);//数字转字符串的函数,最后结果存储到字符串str里 strcat(str,ext);//字符串拼接,用于生成最终的文件名,如"1.txt""2.txt" fp=fopen(str,"w+");//创建文件,准备写入数字 char randnum[10];//存储转换成字符串后的数字,用于拼接换行符后写入文件,直接写入数字会造成各数字间无间距,不能区分。 for(j=0;j<100;j++) { for(k=0;k<1000;k++) { randnumber=rand();//生成随机数 sprintf(randnum,"%d",randnumber);//随机数转成字符串 strcat(randnum,"\n");//拼接换行符 fprintf(fp,randnum);//完成写入一行的操作 } } fclose(fp);//写完一个文件后,关闭文件指针 } } //生成25万个随机数的函数,与上个函数一样,2.5亿个数的运行时间过长,本次测试将规模缩小到25万个随机数 void CreateNumFiles_Less() { int i,j,k; int randnumber; FILE *fp; char str[10]; char ext[5]=".txt"; for(i=0;i<25;i++) { sprintf(str,"%d",i+1); strcat(str,ext); fp=fopen(str,"w+"); char randnum[10]; for(j=0;j<100;j++) { for(k=0;k<100;k++) { randnumber=rand(); sprintf(randnum,"%d",randnumber); strcat(randnum,"\n"); fprintf(fp,randnum); } } fclose(fp); } } //只测试非负数的情况; //假如考虑负数的话,需增加一个2-Bitmap数组. //int a[]={1, 3, 5, 7, 9, 1, 3, 5, 7, 1, 3, 5,1, 3, 1,10,2,4,6,8,0};网上程序自带的测试数组,有兴趣的可以自己先测测 //使用25万个数测试,运行时间不超5分钟,运行结果记录到Results的文本文件中。 int main() { int i; memset(flags, 0, sizeof(flags)); /*printf("原数组为:"); for(i=0;i < sizeof(a)/sizeof(int); ++i) { printf("%d ", a[i]); add_one(a[i]); } printf("\r\n");*/ //FILE *fp_read; int filecount=0;//标识文件序号 FILE *fp_read;//统计操作时用于打开存数字的文本文件 char str[10];//用于存储数字,作为文件名的前半部分 char ext[5]=".txt";//扩展名txt,用于拼接字符串生成相应的文件名 char buf[10];//缓冲区,用于读取数字文件时存储读到的数字 int tempint;//对于文本里读出的每个数,tempint用于存储该数字 //遍历25个文件,首先拼接文件名,再读取每行字符,转成整数后进行置位操作 for(filecount=0;filecount<25;filecount++) { sprintf(str,"%d",filecount+1); strcat(str,ext); fp_read=fopen(str,"r"); if(filecount==0) { if(fp_read==NULL) CreateNumFiles_Less(); } while(!feof(fp_read)) { fgets(buf,10,fp_read); tempint=atoi(buf); //printf("%d\n",tempint); add_one(tempint); } fclose(fp_read); printf("第%d个文件读取完成!\n",filecount+1); } //首先新建文本文件,再遍历标识数组,把出现一次的数字写入到Result.txt文件中 FILE *fp_result; fp_result=fopen("Result.txt","w+"); fprintf(fp_result,"只出现过一次的数:"); for(i=0;i < 32768; ++i) { if(get_val(i) == 1) fprintf(fp_result,"%d\n",i); } fclose(fp_result); printf("执行完毕\n"); return 0; }
相关文章推荐
- 在2.5亿个整数中找出不重复的整数的C++实现源代码
- 2.5亿个整数中找出不重复的整数
- 在2.5亿个整数中找出不重复的整数
- 问题描述如下: 有2.5亿个整数(这2.5亿个整数存储在一个数组里面,至于数组是放在外存还是内存,没有进一步具体说明); 要求找出这2.5亿个数字里面,不重复的数字的个数; 另外,可用的内存限定为600M; 要求算法尽量高效,最优;
- 一个含n个元素的整数数组至少存在一个重复数, 请编程实现,在O(n)时间内找出其中任意一个重复数。
- 2.5亿个整数中找出不重复的整数 bitmap
- 大数据-25亿个数找出不重复的整数-双层桶-代码
- 运用bitmap解决一道海量数据处理面试题:在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数。
- 运用bitmap解决一道海量数据处理面试题:在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数。
- 看不懂自己写的代码,这对一个职业程序员来说是不可饶恕的--完美可以因天赋而成,也可通过无情的重复和实验实现。因为我不具有前者,我就一直坚持着后者。
- 对多个Linerlayout设置点击事件,并实现Activity的跳转。(用Switch简化多次设置点击事件的重复代码)
- leetcode:java.T018_4Sum---给定一个整数数组,找出a + b + c + d = target的唯一解,不能有重复元素组
- Java实现找出数组中重复次数最多的元素以及个数
- php实现二维数组出去重复的代码
- Ajax校验是否重复的实现代码
- 软件开发者面试百问-----有一个数组,里面是从1到1,000,000的整数,其中有一个数字出现了两次,你怎么找出那个重复的数字?
- 一个有n个整数的递增有序数组。对它进行向左或向右循环移动若干次后,要求给出一个代码实现,尽可能快地从这个数组中寻找指定值所在的位置
- 两行Python代码实现IP地址与十进制整数互相转换
- 过滤掉PHP数组中的重复值的实现代码
- 利用位运算实现两个整数的加法运算,请代码实现,并作简要说明。