给10^7个数据量的磁盘文件进行排序

输入:给定一个文件,里面最多含有n个不重复的正整数(也就是说可能含有少于n个不重复正整数),且其中每个数都小于等于n,n=10^7。
输出:得到按从小到大升序排列的包含所有输入的整数的列表。
条件:最多有大约1MB的内存空间可用,但磁盘空间足够。且要求运行时间在5分钟以下,10秒为最佳结果。分析:下面咱们来一步一步的解决这个问题,
    1、归并排序。你可能会想到把磁盘文件进行归并排序,但题目要求你只有1MB的内存空间可用,所以,归并排序这个方法不行。
    2、位图方案。熟悉位图的朋友可能会想到用位图来表示这个文件集合。例如正如编程珠玑一书上所述,用一个20位长的字符串来表示一个所有元素都小于20的简单的非负整数集合,边框用如下字符串来表示集合

(1)位图方法,原理很简单,但是,主要学习c语言中的文件打开关闭,同时一定注意fseek啊,啊,啊,

 1 //位图方法,适用于无重复,有一定范围的排序
 2 //从1到10^7个数排序
 3 //500万是0.625M分成两次
 4 #include <iostream>
 5 #include <ctime>
 6 #include <bitset>
 7 #include <assert.h>
 8 using namespace std;
 9 char * filepath="unsort.txt";
10 char * filesort="sort.txt";
11 #define max_each 5000000
12 #define size 10000000
13 
14 int num[size+1];
15 void createrandom()
16 {
17      FILE *fp = fopen("unsort.txt", "w");  
18     assert(fp);  
19    int n;
20     for ( n = 1; n <= size; n++)    
21         //之前此处写成了n=0;n<size。导致下面有一段小程序的测试数据出现了0,特此订正。  
22         num[n] = n;  
23     srand((unsigned)time(NULL));  
24     int i, j;  
25   
26     for (n = 0; n < size; n++)  
27     {  
28         i = (rand() * RAND_MAX + rand()) % 10000000;  
29         j = (rand() * RAND_MAX + rand()) % 10000000;  
30         swap(num[i], num[j]);  
31     }  
32   
33     for (n = 1; n < size; n++)  
34         fprintf(fp, "%d ", num[n]);  
35     fclose(fp); 
36 }
37 
38     
39 int main()
40 {
41     createrandom();
42     clock_t begin=clock();
43     bitset<max_each+1> bit;
44     bit.reset();
45     FILE * unsort_file=fopen(filepath,"r");
46     assert(unsort_file);
47     int num;
48     while(fscanf(unsort_file,"%d ",&num)!=EOF)
49     {
50         if(num<=max_each)
51             bit.set(num,1);
52 
53     }
54     FILE * sort_file=fopen(filesort,"w");
55     assert(sort_file);
56     for(int i=1;i<=max_each;i++)
57         if(bit[i]==1)
58             fprintf(sort_file,"%d ",i);
59     bit.reset();
60     int result = fseek(unsort_file, 0, SEEK_SET);  
61     if (result)  
62         cout << "fseek failed!" << endl;  
63     while(fscanf(unsort_file,"%d ",&num)!=EOF)
64     {
65         if(num>max_each)
66         {
67             num-=max_each;
68             bit.set(num,1);
69         }
70     }
71     for(int i=1;i<=max_each;i++)
72         if(bit[i]==1)
73             fprintf(sort_file,"%d ",i+max_each);
74     clock_t end=clock();
75     cout<<"finish and usetime=  "<<(end-begin)/CLK_TCK<<"s"<<endl;
76     fclose(sort_file);
77     fclose(unsort_file);
78     system("pause");
79 }

归并排序方法:

吐血编程啊,防着july写的,单写还真写不对

  1 //归并排序方法,采用多路归并,没有任何要求,什么样都能拍还是稳定的,就是要多次读写文件
  2 //要求1m内存,而10的7次方个int是40M,要分成40个文件,一个文件1M,25万的数组为1M
  3 #include <iostream>
  4 using namespace std;
  5 #include <ctime>
  6 #include <assert.h>
  7 #include <algorithm>
  8 #define size 10000000
  9 #define onesize 250000
 10 
 11 int readtomem(FILE * fp,int * space)         //读到内存时注意返回读了多少,最多到onesize单可能比那个小
 12 {
 13     int index=0;
 14     while(index<onesize&&fscanf(fp,"%d ",&space[index])!=EOF)
 15     {
 16         index++;
 17     }
 18     return index;
 19 }
 20 
 21 void writetofile(FILE * fp,int * space,int num)        //写的话是写多少个,返回空
 22 {
 23     for(int index=0;index<num;index++)
 24         fprintf(fp,"%d ",space[index]);
 25 }
 26 
 27 string newfilename(int n)                         //起名字
 28 {
 29     char na[128];
 30     sprintf(na,"data%d.txt",n);
 31     return na;
 32 }
 33 
 34 int  memsort()                                 //返回多少个文件
 35 {
 36     int count=0;
 37     FILE * fp=fopen("unsort.txt","r");
 38     assert(fp);
 39     int * space=new int[onesize];
 40     while(true)
 41     {
 42         int read=readtomem(fp,space);
 43         if(read==0)
 44             break;
 45         sort(space,space+read);
 46         count++;
 47         string file=newfilename(count);
 48         FILE * fpout=fopen(file.c_str(),"w");         //file.c_str()将string转换成char *。
 49         assert(fpout);
 50         writetofile(fpout,space,read);
 51         fclose(fpout);
 52     }
 53     fclose(fp);
 54     delete[] space;                                                     //注意是delete[],而不是delete,前面有题写错了
 55     return count;
 56 }
 57 
 58 void merge_sort(int file_count)
 59 {
 60     if(file_count<=0)
 61         return;
 62     FILE **file_array=new FILE*[file_count];                  //FILE××
 63     assert(file_array);
 64     FILE * fp_result=fopen("memert_sort.txt","w");                      //fopen以w可以创建文件
 65     assert(fp_result);
 66     for(int i=0;i<file_count;i++)
 67     {
 68         string file=newfilename(i+1);                //注意i+1
 69         file_array[i]=fopen(file.c_str(),"r");
 70     }
 71     bool *finish=new bool[file_count];
 72     int * result=new int[file_count];
 73     memset(finish,false,sizeof(bool)*file_count);
 74     for(int i=0;i<file_count;i++)
 75     {
 76         fscanf(file_array[i],"%d ",&result[i]);
 77     }
 78     while(true)
 79     {
 80         int index=0;
 81         while(index<file_count&&finish[index])        //判断退出条件,当finish全是true时,退出,跳过那些已经空的文件
 82             index++;
 83         if(index==file_count)
 84             break;
 85         int min=result[index];
 86         int min_index=index;
 87         for(int i=index+1;i<file_count;i++)
 88         {
 89             if(!finish[i]&&result[i]<min)                       //因为中间也有可能有空的,一般最后也有空的
 90             {
 91                 min=result[i];
 92                 min_index=i;
 93             }
 94         }
 95         fprintf(fp_result,"%d ",min);
 96         if(fscanf(file_array[min_index],"%d ",&result[min_index])==EOF)
 97         {
 98             finish[min_index]=true;
 99         }
100     }
101     fclose(fp_result);
102     delete []finish;
103     delete []result;
104     for (int i = 0; i < file_count; i++)  
105         fclose(file_array[i]);  
106     delete [] file_array;  
107 }
108 
109 int main()  
110 {  
111     clock_t start_memory_sort = clock();  
112     int aux_file_num = memsort();  
113     clock_t end_memory_sort = clock();  
114     cout << "The time needs in memory sort: " << end_memory_sort - start_memory_sort << endl;  
115     clock_t start_merge_sort = clock();  
116     merge_sort(aux_file_num);  
117     clock_t end_merge_sort = clock();  
118     cout << "The time needs in merge sort: " << end_merge_sort - start_merge_sort << endl;  
119     system("pause");  
120     return 0;  
121 } 
原文地址:https://www.cnblogs.com/zmlctt/p/3843302.html