赞
踩
//多路归并外排序的实现
//将一个保存在磁盘上的文件内的数据进行排序
//基本思路是:设文件共有m*n条记录, 内存中每次可以对m条记录进行排序
//则排序过程分两步:
//第一步:从磁盘中读入m条记录到内存; 在内存排序; 将排好序的数据写入新文件;
// 重复上述过程n次 共生成n个新文件
//第二步:分配一个文件指针数组 包含n个文件指针,分别指向n个新文件;
// 分配一个整数数组 大小为n 分别顺序读取各个文件的数据
// 分配一个布尔数组 大小为n 指示各个文件是否读完
// 将读入的整数数组中最小的值写入外存 并继续往后读取对应的文件 然后重复这一步 直到所有的文件都读完
这种算法思想常用于大文件排序,文件大小超出内存容量,可以每次读取内存容量的数据进行内存排序,然后进行归并
采用类似思想还可以解决很多海量数据处理的问题,当内存容量不足以一次处理时,通常都是先将大文件分为小文件,然后分而治之
关键程序段:
第一步
- while(1) {
-
- /*将数据读入内存,一次存满一数组*/
- while(i!=mount && (fscanf(in,"%d",&a[i])!=EOF))i++;
-
- /*内存内排序*/
- qsort(a, 0, i-1);
-
- /*将内存中排好的数据写到磁盘*/
-
- while(j!=i)fprintf(out, "%d ",a[j++]);
- if(i!=mount) break;
- }
- for(k=0;k<file_count;k++) {
-
- /*打开所有k个文件*/
- files[k] = fopen(tf_name,"r");
-
- /*让一个k大的数组依次指向每个文件,并用一个k大的bool数组指示此文件有没有读完*/
- if (fscanf(files[k], "%d ", &b[k]) == EOF) b_tag[k]=false;
- }
-
-
-
- while (true) {
- min = b[0];
- min_p = 0;
-
- /*在k个文件的“当前数据”中找最小的*/
- for (k=0;k<file_count;k++) {
- if (b_tag[k]&&b[k]<min) {
- min=b[k];
- min_p = k;
- }
- }
- if (min_p == 0 && !b_tag[0]) break;
-
- /*写入文件*/
- fprintf(out, "%d ", min);
-
- /*然后对应的文件中的指针后移*/
- if (fscanf(files[min_p], "%d ", &b[min_p])==EOF){
- b_tag[min_p] = false;
- }
- }
- ///
-
- #include <iostream>
-
- using namespace std;
-
-
- class ExternSort
- {
- public:
- ExternSort(const char *in, const char *out, int m)
- {
- file_in = new char[strlen(in)+1];
- strcpy(file_in, in);
- file_out = new char[strlen(out)+1];
- strcpy(file_out, out);
- mount = m;
- }
- ~ExternSort()
- {
- delete []file_in;
- delete []file_out;
- }
- int sort()
- {
- FILE *in = NULL;
- FILE *out = NULL;
- FILE **files = NULL;
- if (!(in = fopen(file_in, "r"))){
- cout<<"open file error"<<endl;
- }
- int file_count = 0;
- char tf_name[10];
- int a[mount], k;
- int *b = NULL;
- bool *b_tag = NULL;
- int min, min_p;
- while(1) {
- int i=0, j=0;
- while(i!=mount && (fscanf(in,"%d",&a[i])!=EOF))i++;
- qsort(a, 0, i-1);
-
- sprintf(tf_name,"%d",file_count++);
- out = fopen(tf_name, "w");
-
- while(j!=i)fprintf(out, "%d ",a[j++]);
- fclose(out);
- if(i!=mount) break;
- }
- out = NULL;
-
- files = new FILE*[file_count];
- b = new int[file_count];
- b_tag = new bool[file_count];
-
- memset(files, 0, file_count);
- memset(b, 0, file_count);
- memset(b_tag, true, file_count);
-
- for(k=0;k<file_count;k++) {
- sprintf(tf_name, "%d", k);
- files[k] = fopen(tf_name,"r");
- if (fscanf(files[k], "%d ", &b[k]) == EOF) b_tag[k]=false;
- }
-
- out = fopen(file_out, "a");
-
- while (true) {
- min = b[0];
- min_p = 0;
- for (k=0;k<file_count;k++) {
- if (b_tag[k]&&b[k]<min) {
- min=b[k];
- min_p = k;
- }
- }
- if (min_p == 0 && !b_tag[0]) break;
- fprintf(out, "%d ", min);
- if (fscanf(files[min_p], "%d ", &b[min_p])==EOF){
- b_tag[min_p] = false;
- }
- }
-
-
- fclose(in);
- fclose(out);
- for(k=0;k<file_count;k++) fclose(files[k]);
- for(k=0;k<file_count;k++) {
- sprintf(tf_name, "%d", k);
- remove(tf_name);
- }
-
-
-
- delete[] b;
- delete[] b_tag;
- delete[] files;
-
-
- }
- private:
- char *file_in;
- char *file_out;
- int mount;
- void qsort(int *a, int s, int e)
- {
- int i=s, j=e;
- int temp = a[i];
- if (i<j) {
- while (i<j) {
- while (i<j&&a[j]>=temp)j--;
- a[i] = a[j];
- while (i<j&&a[i]<=temp)i++;
- a[j] = a[i];
- }
- a[i] = temp;
- qsort(a, s, i-1);
- qsort(a, i+1, e);
- }
- }
- };
-
- int main(int argc, char *args[])
- {
- FILE *f = fopen("in", "w");
- for(unsigned int i=0; i<10000000;i++) fprintf(f, "%d ", rand()%10000);
- fclose(f);
- ExternSort e = ExternSort("in", "out",100000 );
- e.sort();
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。