手把手教你外排序

2023-10-31

排序总体来说分为两类,数据在内存中的叫做内排序,数据存在磁盘的叫外排序。

一般而言,磁盘中存放的都是大型数据,所以,外排序主要是应用于磁盘中大型数据的

一.排序思想

对于外排序而言,因为待排的数据往往远大于内存容量,所以在排序时通常将数据切分,切分成能在内存中排序的大小,将分成的小块依次在内存中排好序后按归并的思路进行整合即可。

我们这里举例子说话:

假设我们有一组100G的数据,已知内存最多存放20G,那么我们把这100G的数据切分成5份,每份20G。

将每份数据排序后依次放入新创建的文档中。

注意:此时所有的数据依旧存放在磁盘中。

 将第一、二个文档归并排序,数据依次录入新创建的文档。

 将存有40G的文档与第三个文档归并排序,同时依次录入新创建的文档。

 按这样进行直到最后一个小文档也被归并完成。

 外排序结束。

值得注意的是,所有的数据均是被存放在了磁盘中,只有在进行数据间的归并排序和最初小磁盘排序时是在内存中进行。

二.代码实现

实现外排序,需要一定的文件操作知识,希望大家先自己尝试实现它,这样更有利于能力的提升。

void Cut_FileData(const char* filename);
void MergeSort_File(const char* file1, const char* file2, const char* filemix);

void main()
{
    Cut_FileData("总文件路径");
    //进行小份数据之间的归并
    char file1[100] = "小文件1路径";
    char file2[100] = "小文件2路径";
    char filemix[100] = "第一次合并后文件路径";
    for (int i = 0; i < 4; i++)//总共份数减一次归并
    {
        MergeSort_File(file1, file2, filemix);
        sprintf(file2, "D:\\git all\\file%d.txt", i + 3);
        memcpy(file1, filemix, sizeof(char) * 100);
        if(i < 1)
            sprintf(filemix, "第%d次合并后文件路径.txt", i + 2);
        else 
            sprintf(filemix, "最终排序完成文件路径");
    }
}

void Cut_FileData(const char* filename)
{
    FILE* fileorg = fopen(filename, "r");
    if (fileorg == NULL) cout << "fileorg failure\n";
    int gap = 20;//总共有100个数据,分成5份,每份20个数据
    for (int i = 0; i < 5; i++)//分成5小份
    {
        int n = 0;
        vector<int> arr;
        while (n++ < 20)
        {
            int num = 0;
            fscanf(fileorg, "%d\n", &num);
            arr.push_back(num);
        }
        sort(arr.begin(), arr.end());
        char min_filename[100] = "1";//创建每一小份的文件数据
        sprintf(min_filename, "第%d小份文件.txt", i + 1);
        FILE* newfile = fopen(min_filename, "w");
        if (newfile == NULL)
        {
            cout << "newfile failure\n";
            exit(-1);
        }
        for (auto x : arr)
        {
            fprintf(newfile, "%d\n", x);
        }
        fclose(newfile);
    }
    fclose(fileorg);
}

void MergeSort_File(const char* file1, const char* file2, const char* filemix)
{
    FILE* filea = fopen(file1, "r");
    if (filea == NULL)
    {
        cout << "filea failure\n";
        exit(-1);
    }
    FILE* fileb = fopen(file2, "r");
    if (fileb == NULL)
    {
        cout << "fileb failure\n";
        exit(-1);
    }
    FILE* filesum = fopen(filemix, "w");
    if (filesum == NULL)
    {
        cout << "filesum failure\n";
        exit(-1);
    }
    int num1 = 0, num2 = 0;
    int ret1 = fscanf(filea, "%d\n", &num1);
    int ret2 = fscanf(fileb, "%d\n", &num2);
    while (ret1 != EOF && ret2 != EOF)//读取文件相当于归并往前走一位, 所以每比较一次就只需要让入数据的小磁盘读取下一个数据即可
    {
        if (num1 <= num2)
        {
            fprintf(filesum, "%d\n", num1);
            ret1 = fscanf(filea, "%d\n", &num1);
        }
        else
        {
            fprintf(filesum, "%d\n", num2);
            ret2 = fscanf(fileb, "%d\n", &num2);
        }
    }
    while (ret1 != EOF)
    {
        fprintf(filesum, "%d\n", num1);
        ret1 = fscanf(filea, "%d\n", &num1);
    }
    while (ret2 != EOF)
    {
        fprintf(filesum, "%d\n", num2);
        ret2 = fscanf(fileb, "%d\n", &num2);
    }
    fclose(filea);
    fclose(fileb);
    fclose(filesum);
}



创作不易,麻烦三连支持一下吧

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手把手教你外排序 的相关文章

  • WebBrowser Control 导致整个应用程序变得无响应

    我有一个带有嵌入式 Web 浏览器的 C NET 3 5 应用程序 浏览器被设计为指向远程站点 而不是本地站点 一切工作正常 但是当页面响应缓慢时 这会导致我的整个应用程序变得无响应 直到加载页面 我不介意浏览器在执行任务时没有响应 但应用
  • 什么是具有副作用的表达式?为什么不应将它们传递给宏?

    我在 C 如何编程 一书中看到这样一句话 具有副作用 即变量值被修改 的表达式不应传递给宏 因为宏参数可能会被多次求值 我的问题是什么是具有副作用的表达式以及为什么不应将它们传递给宏 经典的例子是计算两个值的最大值的宏 define MAX
  • 输出 objdump -t 的输出中的“.hidden”是什么意思?

    Example objdump Logger cpp o t 00000000 g F text 00000000 hidden sti 10 Logger cpp 0b2ae32b 这意味着符号的可见性被隐藏 https develope
  • 如何使用c#/VB.NET在word中插入书签

    我正在尝试使用 C 在 Word 文档中添加书签 但它不起作用 而且我在 msdn 文档和互联网上都找不到任何帮助 这就是我正在尝试做的事情 我正在阅读 Word 文档 然后在该文档中搜索关键字 然后将该文本转换为超链接 效果很好 现在 我
  • 如何使用 Unity 动态注册通用类?

    我有一个包含很多类 300 和 BaseClass 的程序集 我想用接口注册一个泛型类 统一后 您必须在 Name如果你想解析接口的对象数组 我想要一个对象数组主视图模型自动地 有没有办法通过反射来自动执行此操作 有什么建议么 示例 伪 p
  • 使用迭代器遍历 boost::ublas 矩阵

    我只是想从头到尾遍历一个矩阵 触及每个元素 然而 我发现升压矩阵没有一个迭代器 而是有两个迭代器 而且我无法弄清楚如何使它们工作以便您可以遍历整个矩阵 typedef boost numeric ublas matrix
  • Web API 2 中的方法名称约定 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 是否有 Web API 2 中使用的约定的列表 以这两种方法为例 两者都可以工作 但都没有用属性来装饰 IHttpActionResu
  • c++ 最大 std::string 长度由堆栈大小或堆大小决定?

    正如问题中所问 std string myVar 它可以容纳的最大字符是由堆栈还是堆决定的 谢谢 默认情况下 分配的内存为std string是动态分配的 注意std string has a max size 函数返回实现支持的最大字符数
  • 如何防止打印屏幕

    我有一个要求 我正在开发的应用程序阻止用户轻松捕获屏幕内容 我已经表示 没有可行的方法可以完全防止这种情况发生 但我正在寻找方法来为这一过程引入一些障碍 我正在使用 C NET 2 0 和 WinForms 你不能 您能做的最好的事情就是在
  • SolrNet:尝试添加和提交时 SolrConnectionException (400) 错误请求

    我已经到了 SolrNet 执行 Add 方法的地步 但是当我尝试 Commit 时 我收到了错误 以下是我的 schema xml 模型 调用它的代码以及我得到的错误 更奇怪的是 尽管出现错误 但在我重新启动 Tomcat 后 该模型仍会
  • 将 boost::iostreams::mapped_file_source 与 std::multimap 一起使用

    我有相当大量的数据需要分析 每个文件大约有 5gig 每个文件的格式如下 xxxxx yyyyy 键和值都可以重复 但键是按升序排列的 我正在尝试使用内存映射文件来实现此目的 然后找到所需的键并使用它们 这是我写的 if data file
  • 找到两个值的平均值的正确方法是什么?

    我最近了解到整数溢出是 C 中的未定义行为 附带问题 C 中也是 UB 吗 在 C 编程中 您通常需要求两个值的平均值a and b 然而做 a b 2可能会导致溢出和未定义的行为 所以我的问题是 找到两个值的平均值的正确方法是什么a an
  • 以编程方式打开网页并以字符串形式检索其 html 包含内容

    我有一个 Facebook 帐户 我想提取我朋友的照片及其个人详细信息 例如 出生日期 就读学校 等 我能够提取我每个朋友帐户的 Facebook 首页的地址 但我不知道如何以编程方式打开我每个朋友首页的网页并将 html 包含保存为字符串
  • 寻找自定义 SynchronizationContext 的示例(单元测试所需)

    我需要定制同步上下文 http msdn microsoft com en us library system threading synchronizationcontext aspx that 拥有一个运行 Posts 和 Sends
  • 无法在 Visual Studio Code 的 C# 输出上键入任何内容

    所以我试图在 vscode 上运行一个非常基本的 C 程序 代码如下 using System namespace HelloWorld class Program static void Main string args string N
  • Web Api 2 在 OWIN 中间件中获取控制器和操作名称?

    如何在自定义 OWIN 中间件中检索 api 控制器名称和 api 操作名称 我可以在消息处理程序内部执行此操作 如下所示 var config request GetConfiguration var routeData config R
  • timeval_subtract 解释

    使用 timeval subtract 函数来查找两个 struct timeval 类型之间经过的时间 有人可以解释一下用于 通过更新 y 执行后续减法的进位 和其他部分的目的和逐步数学吗 我了解该函数的目的以及如何在程序中实现它 但我想
  • 隐藏 MediaPlayer 控件(Microsoft 媒体平台播放器框架)

    我在 c xaml 应用程序中使用 MMP PF 提供我自己的控制元素来处理播放器 这就是为什么我想隐藏 禁用出现在底部的本机控件 在屏幕截图的屏幕中间 这只是使用了一个主题 有人知道该怎么做吗 我没能找到合适的房产 像这样使用 axWin
  • 如何将curlpp 添加到我的项目中?

    我正在尝试从 vb net 过渡到 C 但我陷入了困境 我从下载了curpp这给了我一个 dll exp 和 lib 文件 我将包含这 3 个文件的目录添加到项目属性中的 附加库目录 链接器 gt 常规 接下来 我将 ws2 32 lib
  • 如何让浏览器后退按钮通过 AJAX 调用带您返回?

    我有一个页面 上面有很多动态生成的复选框 当用户单击这些复选框时 页面上的许多内容会通过 ajax 动态更改 最终用户抱怨 在点击提交然后点击后退按钮更改某些内容后 他们的选择被破坏了 他们必须重新做一遍 我见过一些网站 gmail fac

随机推荐