当前位置: 首页 > 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数字格式不…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...