当前位置: 首页 > news >正文

(排序10)归并排序的外排序应用(文件排序)

TIPS

  1. 在一些文件操作函数当中,fputc与fgetc这两个函数都是针对字符的,如果说你需要往文件里面去放入整形啊等等,不是字符的类型,这时候就用fprintf,fscanf在参数里面数据类型控制一下就可以。但是话说回来,数据文件的话分为文本文件与二进制文件,文件里面的信息唯有二进制信息或者字符ASCII码,然后当你点开文件解析出来的时候都是强制解析成字符的。
  2. 对于C文件操作我还是想再补充几点:首先对于这两个函数fgetc,fputc他们针对的都是字符,比如说可以从内存当中往文件(以文件作为外部输出设备的例子)当中去放字符,也可以从文件当中往内存里面读出来一个字符,但无论如何,他针对的数据类型只有字符;
  3. 然后对于这两个函数fgets与fputs,他们针对的是一行字符串的输入与输出,这边尤其要注意在文件当中每一行字符串的末尾都是默认带有一个换行符\n,这个换行符的话也是需要计数的(参照fgets的参数),并且如果说条件允许也是会被拷贝到内存当中,并且文件指针一旦碰到了这个换行符,它也会换行;
  4. 对于fprintf, fscanf这两个函数来说的话,他们针对的是格式化字符串的输入输出,并且最大的优势与亮点就是说他们的类型很是自由,比如说我想往文件里面放入一个数字,然后我假设要从文件里面过一会儿读出这个数字重新到内存里面来,这时候就不好用fgetc,fputc。因为那两个的话是针对于字符的,这时候就用fprintf,fscanf加%d格式化非常nice。
  5. 最后对于这两个函数sscanf,sprintf来说,这两个函数的功能分别是从字符串当中去抠东西下来放到变量当中,粘连一些东西或者自己添油加醋一些合成一个新字符串。
    在这里插入图片描述
    在这里插入图片描述

归并排序的外排序(文件排序)

  1. 文件排序的话,主要是针对大文件,如果你针对小文件的话就没有意义了。但这边总不能真正的给500个g的数据吧,我们这边就模拟一下
  2. 现在假设有海量的排序数据,那么他这个数据肯定是在文件当中,在磁盘当中,因为磁盘相对于内存大太多了。然后如果我们要对这些数据进行排序的话,不能把他们全部一下子加载到内存里面,因为内存没有这么大
  3. 这时候我们只能用归并排序的思想,归并排序就是说比如说有两段有序的数据,这一段是有序的,那一段也是有序的。然后我们就开一个新的地方,然后每次取小的下来给他放到新的地方里面,就这样把两个有序区间给他归并到一个有序区间。好好去想一想归并的四个生动表述过程。
    在这里插入图片描述
  4. 归并排序的话,既可以把它看成内排序,它也可以搞成外排序。但无论如何他都具有O(N)的空间复杂度,所以说是蛮消耗存储空间的。所以说在内排序当中,它跟快速排序相比的话逊一点,内排序综合快排取胜
  5. 然后现在当数据在文件当中的话,前面的那些快的排序:堆排啊,快排啊都不好弄了,堆排与快排的话都需要随机访问这个大前提,像数组的话很友好,能够支持随机访问,但文件的话就不能进行随机访问了,就算你可以去移动文件指针那也非常非常慢,磁盘的速度相比较于内存而言慢太多了,差异在几百几千倍。所以外排用归并。
  6. 但在归并的过程当中,如果说你用递归的思想,比如说把十个g的文件给他,先分成5个g,5个g,那我如果想要归并的话,首先得确保这两个五个g的文件数据是有序的。那该怎么确保呢?是不是相当于又要继续划分下去,那这样划分下去,不是要划分死了吗?而且我们真正在归并的时候,为了效率提高,我们一定要借助于内存,而不是全部在慢吞吞的磁盘里面。
  7. 所以总的思路就是这样:首先把大文件给他平均分割成N份,然后保证每一份的大小都可以加载到内存当中(我必须借助于内存,没办法,不然纯硬盘里面就慢到猴年马月了),然后因为我等会儿要依托这个每一份的划分出来的小文件为基准量不断向上归并,所以说前提是这些划分出来的小文件必须有序,由于他们现在倒是能够加载到内存里面,所以说先把他们读到内存里面用快速排序把他们先排成有序的
  8. 然后在内存里面给它全部把数据排成有序之后再写回小文件当中。那么这时我们就达到了文件中归并的先决条件。现在都是一个一个有序的小文件了。
  9. 首先就是对磁盘当中的海量数据不断的读,然后用一个变量去控制一下,比如说我现在假定每个小文件里面的数据个数是十个,那么在不断读取的过程当中,每读到十个的时候,然后此时此刻停顿一下,把这十个数据给他,在内存当中快速排序一下,并且给他去创建一个新的文件,并且把这十个在内存当中已经有序的数据给他读到那个文件里面去。当然里面有一些具体的细节的话,就去处理一下就可以,包括边界问题呀等等代码逻辑处理好就可以。
  10. 然后接下来就是文件之间的归并。这时候就肯定不能在内存当中了,因为内存里面已经放不下两个文件合起来这么一个数据量。因为归并排序的话,它的空间复杂度必须是O(N)。然后如果说两两一归并的话,有个很恶心的问题,就是取名字的问题。我们虽然采用非递归归并,但其实也可以不用去两两一归并,可以如下:
    在这里插入图片描述

实际代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define ALL_NUMBER 10000
#define EVERY_NUMBER 1000
#define NAME_MAX 100
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
int GetMidNumi(int* arr, int left, int right)
{int mid = (left + right) / 2;if (arr[left] < arr[mid]){if (arr[left] > arr[right]){return left;}else{return arr[mid] < arr[right] ? mid : right;}}else{if (arr[right] > arr[left]){return left;}else{return arr[mid] > arr[right] ? mid : right;}}
}
void QuickSort(int* arr, int left, int  right)
{if (left >= right){return;}int begin = left;int end = right;int midi = GetMidNumi(arr, left, right);Swap(arr + left, arr + midi);int keyi = left;while (left < right){while (left < right && arr[right] >= arr[keyi]){right--;}while (left < right && arr[left] <= arr[keyi]){left++;}Swap(arr + left, arr + right);}Swap(arr + left, arr + keyi);keyi = left;QuickSort(arr, begin, keyi - 1);QuickSort(arr, keyi + 1, end);
}
void CreateNumber()
{srand((unsigned int)time(NULL));FILE* pf = fopen("number.txt", "w");if (pf == NULL){perror("fopen failed");return;}for (int i = 0; i < ALL_NUMBER; i++){int num = rand();fprintf(pf, "%d\n", num);}fclose(pf);pf = NULL;
}
void MergeSortFile(char* file1, char* file2, char* file)
{FILE* pf1 = fopen(file1, "r");if (pf1 == NULL){perror("fopen failed");return;}FILE* pf2 = fopen(file2, "r");if (pf2 == NULL){perror("fopen failed");return;}FILE* pf = fopen(file, "w");if (pf == NULL){perror("fopen failed");return;}int num1 = 0;int num2 = 0;int ret1 = fscanf(pf1, "%d", &num1);int ret2 = fscanf(pf2, "%d", &num2);while (ret1 != EOF && ret2 != EOF){if (num1 < num2){fprintf(pf, "%d\n", num1);ret1 = fscanf(pf1, "%d", &num1);}else{fprintf(pf, "%d\n", num2);ret2 = fscanf(pf2, "%d", &num2);}}while (ret1 != EOF){fprintf(pf, "%d\n", num1);ret1 = fscanf(pf1, "%d", &num1);}while (ret2 != EOF){fprintf(pf, "%d\n", num2);ret2 = fscanf(pf2, "%d", &num2);}fclose(pf1);fclose(pf2);fclose(pf);
}
void Cover(char* file1, char* file2)
{FILE* pf1 = fopen(file1, "r");if (pf1 == NULL){perror("fopen failed");return;}FILE* pf2 = fopen(file2, "w");if (pf2 == NULL){perror("fopen failed");return;}int num = 0;int res = 0;while (fscanf(pf1, "%d", &num) != EOF){fprintf(pf2, "%d\n", num);}fclose(pf1);fclose(pf2);
}
int main()
{CreateNumber();FILE* pf = fopen("number.txt", "r");if (pf == NULL){perror("fopen failed");return;}int arr[EVERY_NUMBER] = { 0 };char file1[NAME_MAX] = { 0 };char file2[NAME_MAX] = { 0 };char file[NAME_MAX] = { 0 };int res = 0;int i = 0;int count = 0;while ((res = fscanf(pf, "%d", &arr[i++])) != EOF){if (i == EVERY_NUMBER){count++;if (count == 1){sprintf(file1, "%d", count);}sprintf(file2, "%d", count);QuickSort(arr, 0, EVERY_NUMBER - 1);i = 0;FILE* _pf = fopen(file2, "w");if (_pf == NULL){perror("fopen failed");return 1;}for (int j = 0; j < EVERY_NUMBER; j++){fprintf(_pf, "%d\n", arr[j]);}fclose(_pf);if (count > 1){sprintf(file, "%s%s", file1, file2);MergeSortFile(file1, file2, file);strcpy(file1, file);}}}fclose(pf);Cover(file, "number.txt");return 0;
}

相关文章:

(排序10)归并排序的外排序应用(文件排序)

TIPS 在一些文件操作函数当中&#xff0c;fputc与fgetc这两个函数都是针对字符的&#xff0c;如果说你需要往文件里面去放入整形啊等等&#xff0c;不是字符的类型&#xff0c;这时候就用fprintf&#xff0c;fscanf在参数里面数据类型控制一下就可以。但是话说回来&#xff0c…...

浅谈根号分治与分块

文章目录 1. 根号分治哈希冲突 2. 线性分块引入教主的魔法[CQOI2011] 动态逆序对[国家集训队] 排队[HNOI2010] 弹飞绵羊蒲公英 1. 根号分治 哈希冲突 题目1 n n n 个数&#xff0c; m m m 次操作。操作 1 为修改某一个数的值&#xff0c;操作 2 为查询所有满足下标模 x x x …...

(OpenAI)ChatGPT注册登录常见问题错误代码及其解决方法

在使用 ChatGPT 的时候我们可能会碰到一些错误的代码&#xff0c;本文统一来介绍一下每一种错误以及解决方法。 错误代码1. 不能在当前国家使用 出现场景&#xff1a;一般在注册或登录的时候会出现。 原因&#xff1a;主要是ChatGPT检测到当前访问所在的地区不允许访问导致。 …...

MySQL主从复制、读写分离(MayCat2)实现数据同步

文章目录 1.MySQL主从复制原理。2.实现MySQL主从复制&#xff08;一主两从&#xff09;。3.基于MySQL一主两从配置&#xff0c;完成MySQL读写分离配置。&#xff08;MyCat2&#xff09; 1.MySQL主从复制原理。 MySQL主从复制是一个异步的复制过程&#xff0c;底层是基于Mysql数…...

Linux 云服务器好用吗?(解读Linux云服务器的特点优势)

​  如今&#xff0c;云计算越来越受欢迎&#xff0c;许多公司正在将业务转移到那里。企业向云过渡的主要原因是它提供的众多服务&#xff0c;包括安全和充足的存储、数据库、服务器和其他关键元素。 作为相对前|沿的技术之一&#xff0c;云建立在虚拟服务器上。Linux 服务器…...

研读Rust圣经解析——Rust learn-8(match,if-let简洁控制流,包管理)

研读Rust圣经解析——Rust learn-8&#xff08;match,if-let简洁控制流&#xff0c;包管理&#xff09; matchother和占位符_区别 easy matchenum matchno valuematch inner Option matchmore better way if-let整洁控制包管理模块(mod)拆分声明modpub公开use展开引用拆解模块结…...

G8期刊《全体育》期刊简介及投稿要求

G8期刊《全体育》期刊简介及投稿要求 《全体育》是由湖南体育产业集团有限公司主管、体坛传媒集团股份有限公司主办、中教体育 出版发行的体育综合性期刊。 主管&#xff1a;湖南体育产业集团有限公司 主办&#xff1a;体坛传媒集团股份有限公司 国内刊号&#xff1a;CN4…...

数据结构和算法学习记录——层序遍历(层次遍历)、二叉树遍历的应用(输出二叉树中的叶节点、求二叉树的高度、二元运算表达式树及其遍历、由两种遍历序列确定二叉树)

目录 层序遍历 思路图解 代码实现 二叉树遍历的应用 输出二叉树中的叶节点 代码实现 求二叉树的高度 思路图解 代码实现 二元运算表达式树及其遍历 由两种遍历序列确定二叉树 层序遍历 层序遍历可以通过一个队列来实现&#xff0c;其基本过程为&#xff1a; 先根…...

【Neo4j数据库】图数据库_Neo4j增加节点(关系)、查询、删除数据库等操作解析(Cypher语句)

【Neo4j数据库】图数据库_Neo4j增加节点&#xff08;关系&#xff09;、查询、删除操作解析&#xff08;Cypher语句&#xff09; 文章目录 【Neo4j数据库】图数据库_Neo4j增加节点&#xff08;关系&#xff09;、查询、删除操作解析&#xff08;Cypher语句&#xff09;1. 介绍2…...

Linux移动文件和文件夹(目录)命令

命令mv 英文move 翻译移动 mv命令可以移动文件或文件夹&#xff08;目录&#xff09;&#xff0c;也可以重命令&#xff08;覆盖&#xff09;文件。 1. 移动文件/重命名 单纯地移动某一个文件直接使用&#xff1a; mv <源文件名称/地址> <新文件名称/地址>这个方法…...

Pandas的应用-5

Pandas是一个强大的数据处理库&#xff0c;它提供了高性能、易于使用的数据结构和数据分析工具。本文将介绍Pandas常用的数据结构和常用的数据分析技术&#xff0c;包括DataFrame的应用、窗口计算、相关性判定、Index的应用、范围索引、分类索引、多级索引以及日期时间索引。 …...

java继承类怎么写

继承类是通过把父类的方法和属性继承到一个类中&#xff0c;而子类的方法和属性是子类自己定义的。 Java中有一个很重要的概念叫做继承&#xff0c;这也是 Java语言的精髓所在。Java语言提供了一种机制&#xff0c;叫做派生类。在 Java中&#xff0c;如果没有实现了某个派生类方…...

面向对象程序设计

OOP 【面向对象程序设计】&#xff08;OOP&#xff09;与【面向过程程序设计】在思维方式上存在着很大的差别。【面向过程程序设计】中&#xff0c;算法是第一位的&#xff0c;数据结构是第二位的&#xff0c;这就明确地表述了程序员的工作方式。首先要确定如何操作数据&#…...

Linux 用户身份切换(su,sudo)

文章目录 Linux 用户身份切换su使用案例 sudo使用案例 visudo与/etc/sudoers单一用户可使用root所有命令&#xff0c;与sudoers文件语法利用wheel用户组以免密码的功能处理visudo有限制的命令操作通过别名创建visudosudo的时间间隔问题sudo搭配su的使用方式 Linux 用户身份切换…...

求倒置数问题

文章目录 求倒置数程序设计程序分析求倒置数 【问题描述】数组A【0,…,n-1】是一个n个不同整数数构成的数组。如果i<j,但是A[i]〉A[j],则这对元素(A[i],A[j])被称为一个倒置(inversion)。设计一个O(nlogn)算法来计算数组中的倒置数量 【输入形式】输入两行,第一行…...

sed(学习)

1、清除环境变量 ​​​​​​profile~/.bash_profile sed -i s#export LD_LIBRARY_PATH.*##g $profile 2、设置环境变量(替换值) sed -i s#export LD_LIBRARY_PATH.*#export LD_LIBRARY_PATH/opt/testlinux/lib#g ~/.bash_profile 3、修改配置文件 sdk_dir/root/test log_dir/…...

B - GCD Subtraction

文章目录 AtCoder Regular Contest 159B - GCD Subtraction AtCoder Regular Contest 159 B - GCD Subtraction 问题&#xff1a;每次A,B都减去gcd(A,B)&#xff0c;求其中一个减到0至少需要多少次主要思路&#xff1a; 首先第一步应该想到每次减去的数&#xff0c;先减去的数…...

解决Failed to load ApplicationContext问题的思路

中文翻译&#xff1a; 加载ApplicationContext失败 第一步&#xff1a;首先检查测试类的注解 以及 依赖 SpringBootTest <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scop…...

基于CAMX大气臭氧来源解析模拟与臭氧成因分析实践技术应用

查看原文>>>基于CAMX大气臭氧来源解析模拟与臭氧成因分析实践技术应用 目录 专题一、大气臭氧污染来源及成因分析技术讲解&#xff1b;CAMx模式初识及臭氧来源解析模拟本地案例配置说明 专题二、CAMx模式编译安装及空气质量模拟案例配置 专题三、CAMx扩展和探测工…...

异常的讲解 (1)

目录 异常入门的案例 异常介绍 基本概念 异常的小结 常见的运行时异常 1.NullPointerException空指针异常 2.ArithmeticException数学运算异常 3.ArraylndexOutOfBoundsException数组下标越界异常 4.ClassCastException类型转换异常 5.NumberFormatException数字格式不…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

如何在Windows本机安装Python并确保与Python.NET兼容

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

轻量级Docker管理工具Docker Switchboard

简介 什么是 Docker Switchboard &#xff1f; Docker Switchboard 是一个轻量级的 Web 应用程序&#xff0c;用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器&#xff0c;使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...

动态规划-1035.不相交的线-力扣(LeetCode)

一、题目解析 光看题目要求和例图&#xff0c;感觉这题好麻烦&#xff0c;直线不能相交啊&#xff0c;每个数字只属于一条连线啊等等&#xff0c;但我们结合题目所给的信息和例图的内容&#xff0c;这不就是最长公共子序列吗&#xff1f;&#xff0c;我们把最长公共子序列连线起…...

react更新页面数据,操作页面,双向数据绑定

// 路由不是组件的直接跳转use client&#xff0c;useEffect&#xff0c;useRouter&#xff0c;需3个结合&#xff0c; use client表示客户端 use client; import { Button,Card, Space,Tag,Table,message,Input } from antd; import { useEffect,useState } from react; impor…...