• [算法]外部排序


    当排序内容太大,不足以全部放入内存进行内部排序,则可把排序内容按可用内存大小分割成多个文件,分别读取文件进行内排,排序结果继续写入文件。最后对所有文件进行归并排序合并成有序大文件。

    外部排序步骤:1、分割数据 2、分别内排 3、归并小文件

    // acm.cpp : Defines the entry point for the console application.
    //
    #include "stdafx.h"
    #pragma warning(disable: 4786)
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <fstream>//加入这个头文件才可以操作文件
    #include <vector>
    #include <algorithm>
    #include "Afx.h"
    using namespace std;
    //分割文件,每个文件n个数据
    int divi_file(char* file_name,int n){
        ifstream in_file;
        in_file.open(file_name);
        if(!in_file)
            return 0;
        char buf[100];
        int count=0,n_file=0;
        ofstream out_file;
        while(!in_file.eof()){
            in_file.getline(buf,100);
            if(count==0){
                char f_name[20];
                sprintf(f_name,"%d.txt",n_file);
                out_file.open(f_name);
                n_file++;
            }
            out_file<<buf<<endl;
            count++;
            if(count>=n){
                count=0;
                out_file.close();
            }
        }
        out_file.close();
        in_file.close();
        return n_file;
    }
    
    //子文件内排序
    void in_sort(int n_file){
        ofstream out_file;
        for(int i=0;i<n_file;++i){
            char f_name[20];
            sprintf(f_name,"%d.txt",i);
            ifstream in_file;
            in_file.open(f_name);
            vector<int> v_sort;
            char buf[100];
            while(!in_file.eof()){
                in_file.getline(buf,100);
                v_sort.push_back(atoi(buf));
            }
            sort(v_sort.begin(),v_sort.end());
            in_file.close();
            out_file.open(f_name);
            int len=v_sort.size();
            for(int j=1;j<len;++j){
                out_file<<v_sort[j];
                if(j!=len-1)
                    out_file<<endl;
            }
            v_sort.clear();
            out_file.close();
        }
    }
    
    //归并两个文件
    void merge_two(char* ifile1,char* ifile2,char* ofile){
        ifstream f1,f2;
        f1.open(ifile1);
        f2.open(ifile2);
        ofstream result;
        result.open(ofile);
        int c1,c2,done1=1,done2=1;
        while(!f1.eof() || !f2.eof() || done1==0 || done2==0){
            char buf[100];
            if(!f1.eof() && done1==1){
                f1.getline(buf,100);
                if(*buf!='\0'){
                    c1=atoi(buf);
                    done1=0;
                }
            }
            if(!f2.eof() && done2==1){
                f2.getline(buf,100);
                if(*buf!='\0'){
                    c2=atoi(buf);
                    done2=0;
                }
            }
            if(done1==0 && done2==0){
                if(c1<c2){
                    result<<c1<<endl;
                    done1=1;
                }else{
                    result<<c2<<endl;
                    done2=1;
                }
            }else{
                if(done1==0){
                    result<<c1<<endl;
                    done1=1;
                }
                if(done2==0){
                    result<<c2<<endl;
                    done2=1;
                }
            }
        }
        f1.close();
        f2.close();
        result.close();
    }
    
    //归并所有子文件
    void merge_all(int n_file){
        if(n_file==1)
            return;
        int n=n_file/2;
        for(int i=0;i<n;++i){
            char f_name1[20],f_name2[20];
            sprintf(f_name1,"%d.txt",i);
            sprintf(f_name2,"%d.txt",n_file-i-1);
            merge_two(f_name1,f_name2,"tmp.txt");
            char cmd[100];
            sprintf(cmd,"del %s",f_name1);
            system(cmd);
            if(n_file!=2)
                sprintf(cmd,"ren %s %s","tmp.txt",f_name1);
            else
                sprintf(cmd,"ren %s %s","tmp.txt","result.txt");
            system(cmd);
        }
        merge_all(n_file/2+n_file%2);
    }
    
    //删除临时文件
    void del_tmp_file(int n_file){
        for(int i=1;i<n_file;++i){
            char f_name[20];
            sprintf(f_name,"%d.txt",i);
            char cmd[100];
            sprintf(cmd,"del %s",f_name);
            system(cmd);
        }
    }
    
    void outer_sort(char* file_path,int n){
        int n_file=divi_file(file_path,n);
        if(n_file==0)
            return;
        cout<<n_file<<endl;
        in_sort(n_file);
        merge_all(n_file);
        del_tmp_file(n_file);
    }

     多路归并时,需要维护一棵败者树来快速查找出多路之中的最小值。见下一篇随笔。

  • 相关阅读:
    java 笔记(4) —— java I/O 流、字节流、字符流
    Java命令参数说明大全
    java 笔记(3) —— 动态代理,静态代理,cglib代理
    java 笔记(2) —— 内部类的作用
    java 笔记(1)-—— JVM基础,内存数据,内存释放,垃圾回收,即时编译技术JIT,高精度类型
    scala学习笔记(1)
    spring 小结
    收集一些java相关的文章
    Troubleshooting JDK
    WebService 的一些基本概念
  • 原文地址:https://www.cnblogs.com/iyjhabc/p/3135066.html
Copyright © 2020-2023  润新知