位图用每个位的值(0 or 1)来表明一个数是否存在,从而减少了内存使用量,也提高了效率。
问题:
输入:所输入的是一个文件,至多包含n个正整数,每个正整数都小于n,n=10,000,000.数字不重复,且不相互关联
输出:经过排序的整数列表
约束:至多1M的可用内存,可用磁盘空间充足。运行时间最多几分钟,最好是10S
特点: 1. 数的范围小; 2. 没有重复数字; 3. 数之间不相连;
实现:
#include<fstream>//FILE #include<ctime> //time const int N = 10000000; //num of records const int SHIFT = 5; const int BITSPERWORD = 32; //sizeof(int)*8 const int MASK = 0x1F; const int SIZE = N/BITSPERWORD+1; int a[SIZE]; inline void clr(int i) { a[i>>SHIFT] &= ~(1<<(i&MASK)); } inline void set(int i) { a[i>>SHIFT] |= (1<<(i&MASK)); } inline int test(int i) { return a[i>>SHIFT] & (1<<(i&MASK)); } FILE* file;//在源文件中排序覆盖 //文件中交换两个数据比较麻烦,就这样生成数据了,可能有重复,结果中去重。 void generateNumbers() { srand((unsigned int)time(NULL)); for(int i=0; i<N; i++) { fprintf(file,"%d /n",(RAND_MAX*rand()+rand())%N);//RAND_MAX=32767 } } void clrBits() { for(int i=0; i<N; i++) clr(i); } void setBits() { rewind(file); int times = N; char c[10]; while((fgets(c,10,file)!=NULL)&×--) { int i = atoi(c); set(i); } } void getSorts() { rewind(file); fprintf(file,"After sort/n"); for(int i=0; i<N; i++) { if(test(i)) { fprintf(file,"%d/n",i); printf("%d/n",i); } } fprintf(file,"The end/n"); } void main() { if((file=fopen("data.txt","w+"))==NULL) printf("Cannot open data.txt./n"); generateNumbers(); clock_t start = clock(); clrBits(); setBits(); getSorts(); clock_t end = clock(); printf("Used %ld ms. /n",end-start); fclose(file); }
下面是生成[1,n]之间的k个不重复随机数的代码:
//[min,max]之间的随机数 int randNum(int min, int max) { srand((unsigned int)time(NULL)); return (RAND_MAX*rand()+rand())%(max-min+1)+min; } void generateRandomNumbers(int* a,int n,int k) { for(int i=0; i<n; i++) a[i]=i+1; for(int i=0; i<k; i++) { int index = randNum(i+1,n-1); int temp = a[i]; a[i] = a[index]; a[index] = temp; } }