zoukankan      html  css  js  c++  java
  • 给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 } 
  • 相关阅读:
    除adsense外适合英文站的国外广告联盟(4/12/2011更新)
    盛大云和阿里云之云主机初体验
    【行文格式】
    在线PDF阅读&编辑网站一览
    做销售不得不看的20部电影
    VS中的Code Snippet来提高开发效率
    10个免费的javascript富文本编辑器(jQuery and nonjQuery)
    【操作命令】
    SQLServer常见查询问题
    代码検索
  • 原文地址:https://www.cnblogs.com/zmlctt/p/3843302.html
Copyright © 2011-2022 走看看