外排序之⽂件归并排序实现

news2024/9/21 4:36:39

外排序之⽂件归并排序实现

在这里插入图片描述

外排序介绍

外排序(External sorting)是指能够处理极⼤量数据的排序算法。通常来说,外排序处理的数据不能
⼀次装⼊内存,只能放在读写较慢的外存储器(通常是硬盘)上。外排序通常采⽤的是⼀种“排序-归
并”的策略。在排序阶段,先读⼊能放在内存中的数据量,将其排序输出到⼀个临时⽂件,依此进
⾏,将待排序数据组织为多个有序的临时⽂件。然后在归并阶段将这些临时⽂件组合为⼀个⼤的有序
⽂件,也即排序结果。

跟外排序对应的就是内排序,我们之前讲的常⻅的排序,都是内排序,他们排序思想适应的是数据在
内存中,⽀持随机访问。归并排序的思想不需要随机访问数据,只需要依次按序列读取数据,所以归
并排序既是⼀个内排序,也是⼀个外排序。

⽂件归并排序思路分析

  1. 读取n个值排序后写到file1,再读取n个值排序后写到file2
  2. file1和file2利⽤归并排序的思想,依次读取⽐较,取⼩的尾插到mfile,mfile归并为⼀个有序⽂件
  3. 将file1和file2删掉,mfile重命名为file1
  4. 再次读取n个数据排序后写到file2
  5. 继续⾛file1和file2归并,重复步骤2,直到⽂件中⽆法读出数据。最后归并出的有序数据放到了
    file1中
    在这里插入图片描述

⽂件归并排序代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void Swap(int* p1, int* p2)
{
 int tmp = *p1;
 *p1 = *p2;
 *p2 = tmp;
}
void AdjustDown(int* a, int n, int parent)
{
 int child = parent * 2 + 1;
 while (child < n)
 {
 // 选出左右孩⼦中⼤的那⼀个
 if (child + 1 < n && a[child + 1] > a[child])
 {
 ++child;
 }
 if (a[child] > a[parent])
 {
 Swap(&a[child], &a[parent]);
 parent = child;
 child = parent * 2 + 1;
 }
 else
 {
 break;
 }
 }
}
void HeapSort(int* a, int n)
{
 // 建堆 -- 向下调整建堆 -- O(N)
 for (int i = (n - 1 - 1) / 2; i >= 0; --i)
 {
 AdjustDown(a, n, i);
 }
 // O(N*logN
 int end = n - 1;
 while (end > 0)
 {
 Swap(&a[end], &a[0]);
 AdjustDown(a, end, 0);
 --end;
 }
}
// file1⽂件的数据和file2⽂件的数据归并到mfile⽂件中
void MergeFile(const char* file1, const char* file2, const char* mfile)
{
 FILE* fout1 = fopen(file1, "r");
 if (fout1 == NULL)
 {
 printf("打开⽂件失败\n");
 exit(-1);
 }
 FILE* fout2 = fopen(file2, "r");
 if (fout2 == NULL)
 {
 printf("打开⽂件失败\n");
 exit(-1);
 }
 FILE* fin = fopen(mfile, "w");
 if (fin == NULL)
 {
 printf("打开⽂件失败\n");
 exit(-1);
 }
 // 这⾥跟内存中数组归并的思想完全类似,只是数据在硬盘⽂件中⽽已
 // 依次读取file1和file2的数据,谁的数据⼩,谁就往mfile⽂件中去写
 // file1和file2其中⼀个⽂件结束后,再把另⼀个⽂件未结束⽂件数据,
 // 依次写到mfile的后⾯
 int num1, num2;
 int ret1 = fscanf(fout1, "%d\n", &num1);
 int ret2 = fscanf(fout2, "%d\n", &num2);
 while (ret1 != EOF && ret2 != EOF)
 {
 if (num1 < num2)
 {
 fprintf(fin, "%d\n", num1);
 ret1 = fscanf(fout1, "%d\n", &num1);
 }
 else
 {
 fprintf(fin, "%d\n", num2);
 ret2 = fscanf(fout2, "%d\n", &num2);
 }
 }
 while (ret1 != EOF)
 {
 fprintf(fin, "%d\n", num1);
 ret1 = fscanf(fout1, "%d\n", &num1);
 }
 while (ret2 != EOF)
 {
 fprintf(fin, "%d\n", num2);
 ret2 = fscanf(fout2, "%d\n", &num2);
 }
 fclose(fout1);
 fclose(fout2);
 fclose(fin);
}
// 返回读取到的数据个数
int ReadNNumSortToFile(FILE* fout, int* a, int n, const char* file)
{
 int x = 0;
 // 读取n个数据放到file
 int i = 0;
 while (i < n && fscanf(fout, "%d", &x) != EOF)
 {
 a[i++] = x;
 }
 // ⼀个数据都没有读到,则说明⽂件已经读到结尾了
 if (i == 0)
 return i;
 // 排序
 HeapSort(a, i);
 FILE* fin = fopen(file, "w");
 if (fout == NULL)
 {
 printf("打开⽂件%s失败\n", file);
 exit(-1);
 }
 for (int j = 0; j < i; j++)
 {
 fprintf(fin, "%d\n", a[j]);
 }
 fclose(fin);
 return i;
}
// MergeSortFile的第⼆个是每次取多少个数据到内存中排序,然后写到⼀个⼩⽂件进⾏归并
// 这个n给多少取决于我们有多少合理的内存可以利⽤,相对⽽⾔n越⼤,更多数据到内存中排序后,
// 再⾛⽂件归并排序,整体程序会越快⼀些。
void MergeSortFile(const char* file, int n)
{
 FILE* fout = fopen(file, "r");
 if (fout == NULL)
 {
 printf("打开⽂件%s失败\n", file);
 exit(-1);
 }
 
 int i = 0;
 int x = 0;
 const char* file1 = "file1";
 const char* file2 = "file2";
 const char* mfile = "mfile";
 // 分割成⼀段⼀段数据,内存排序后写到,⼩⽂件,
 int* a = (int*)malloc(sizeof(int) * n);
 if (a == NULL)
 {
 perror("malloc fail");
 return;
 }
 // 分别读取前n个数据排序后,写到file1和file2⽂件
 ReadNNumSortToFile(fout, a, n, file1);
 ReadNNumSortToFile(fout, a, n, file2);
 while (1)
 {
 // file1和file2⽂件归并到mfile⽂件中
 MergeFile(file1, file2, mfile);
 // 删除file1和file2
 if (remove(file1) != 0 || remove(file2) != 0)
 {
 perror("Error deleting file");
 return;
 }
 
 // 将mfile重命名为file1
 if (rename(mfile, file1) != 0)
 {
 perror("Error renaming file");
 return;
 }
 // 读取N个数据到file2,继续⾛归并
 // 如果⼀个数据都没读到,则归并结束了
 if (ReadNNumSortToFile(fout, a, n, file2) == 0)
 {
 break;
 }
 }
 printf("%s⽂件成功排序到%s\n", file, file1);
 fclose(fout);
 free(a);
}
// 创建N个随机数,写到⽂件中
void CreateNDate()
{
 // 造数据
 int n = 1000000;
 srand(time(0));
 const char* file = "data.txt";
 FILE* fin = fopen(file, "w");
 if (fin == NULL)
 {
 perror("fopen error");
 return;
 }
 for (int i = 0; i < n; ++i)
 {
 int x = rand() + i;
 fprintf(fin, "%d\n", x);
 }
 fclose(fin);
}
int main()
{
 //CreateNDate();
 MergeSortFile("data.txt", 100000);
 return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2086670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring+SpringWeb+MyBatis三大框架整合教程 实现先前后端交互搭建

目录 1. 创建项目 2. 导入所依赖的 jar 包 3. 配置MyBatis 4. 配置spring事务管理 5. 配置Spring * Spring配置代码解读 6. dao层 7. mappers映射文件 8. common层 9. service层 10. web层 11. 测试 ssm大合体&#xff01; 1. 创建项目 &#x1f4cd;创建一个J…

【C++ Primer Plus习题】6.7

问题: 解答: #include <iostream> #include <cctype> using namespace std;int main() {string words;int vowel 0;int consonant 0;int other0;cout << "请输入一个单词(q结束):";cin >> words;while (words!"q"){if (!isalph…

编成笔记-atan2函数学习分析

分析atan2函数 1. 前言 2. atan2函数分析 tanθy/x : 当(x,y) 在第一象限&#xff0c;0 < θ < π/2当(x,y) 在第二象限&#xff0c;π/2 < θ ≤ π当(x,y) 在第三象限&#xff0c;− π < θ < − π/2当(x,y) 在第四象限&#xff0c;− π/2 < θ <…

动态读取nacos中修改的项目配置文件

本项目用的还是springboot项目&#xff0c;咱们直接上代码 一&#xff1a;首先看下nacos中需要动态获取的属性 二&#xff1a;把需要动态读取的配置类中的属性整理一个实体类 mport lombok.Data; import org.springframework.boot.context.properties.ConfigurationPropert…

微信公众号等工具 3 — 使用 Markdown Nice 写文章

文章目录 操作步骤STEP 1. 进入微信公众号文章编辑界面STEP 2. Markdown Nice 将 3 个重要的功能嵌入到了微信公众号编辑器中STEP 3. 在 Markdown Nice 界面编辑内容STEP 4. 导入/粘贴/直接在编辑器中编辑 Markdown → 点击左下角的预览效果 操作步骤 STEP 1. 进入微信公众号文…

BUUCTF二维码1

九张撕碎二维码碎片。不会让人拼起来吧&#xff01;看了大神们得博客竟然是真的&#xff0c;这是ctf的题吗&#xff01;是考验人的耐性吧&#xff01; 我勉为其难讲一下PS怎么拼图&#xff0c;首先要把九张碎片抠图&#xff0c;背景变透明&#xff0c;ps可以但是太麻烦&#xf…

(亲测有效)spring cloud+Vue微服务项目云服务器部署(宝塔)

我的另一篇博客&#xff0c;有兴趣可以看看&#xff0c;部署思路都是一样的。 &#xff08;亲测有效&#xff09;SpringBootVue项目云服务器部署&#xff08;宝塔&#xff09;_springboot 宝塔部署-CSDN博客 目录 一、准备工作 购买云服务器 登录云服务器 安装宝塔 二、jdk…

项目技巧二

java中Date和mysql数据库datetime数据类型 数据库中的 datetime 类型&#xff1a; 大多数关系型数据库&#xff08;如 MySQL, SQL Server, PostgreSQL 等&#xff09;都提供了 datetime 类型&#xff0c;用于存储日期和时间信息。这些数据库中的 datetime 类型通常遵循 ISO 86…

金九银十跳槽季,最新自动化测试面试题合集

前言 Hello,大家好。金九银十也不远了&#xff0c;有的人盼望升职加薪&#xff0c;有的人立了新的Flag&#xff0c;有跳槽计划的该提上日程了。为解大伙的燃眉之急&#xff0c;今天分享自动化面试题预热一波&#xff0c;欢迎留言区补充评论&#xff01; 一、请描述一下自动化测…

sqli-labs靶场通关攻略(四十一到五十关)

sqli-labs-master靶场第四十一关 一&#xff0c;查看数据库 ?id-1 union select 1,2,database()-- 二&#xff0c;查看表名 ?id-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase()-- 三&#xff0c;查看users表中…

python学习之路 - python对mysql的数据操作

目录 一、python对mysql的数据操作1、前期准备2、连接mysql3、创建表5、插入表4、查询表 一、python对mysql的数据操作 1、前期准备 使用python对mysql进行相关操作前&#xff0c;需要安装pymysql。执行pip install pymysql命令即可如果具体不知道如何操作&#xff0c;可以查…

导入pyBigWig包

今天复现论文时&#xff0c;看到了一种叫做bigwig格式的数据&#xff0c;创建和访问该格式文件需要用到pybigwig包&#xff0c;在此过程中遇到了一些问题&#xff0c;记录一下。 介绍 pybigwig的使用依赖于两个C库&#xff0c;所谓C库就是C语言编写的python库。 正如在pypi官…

聚类算法-DBSCAN

文章目录 一、DBSCAN介绍1.含义2.DBSCAN 的核心概念3.DBSCAN算法参数 二、代码实现1.数据预处理2.DBSCAN聚类3.计算轮廓系数4.全部代码 三、总结 一、DBSCAN介绍 1.含义 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;是一种基…

llama-cpp-python编译失败,解决方案安装wheel文件

https://abetlen.github.io/llama-cpp-python/whl/cu121/llama-cpp-python/编译失败&#xff1a; 解决方案&#xff1a;使用轮子镜像

Clion/Vs中wcout输出中文不显示的解决办法

本来要写个输出所有窗口的代码&#xff0c;但是结果文字一直不输出&#xff0c;又试了试发现只是汉字不输出&#xff1a; #include <windows.h> #include <iostream> #include <vector> #include <string>std::vector<std::wstring> windowTitl…

数据结构(6.4_4)——Floyd算法

Floyd算法 第一步&#xff1a;建立两个二维数组&#xff0c;一个用来存放所有顶点&#xff0c;一个用来存放顶点之间的中转点 第二步&#xff1a;循环遍历A矩阵&#xff0c;若,则&#xff0c;&#xff1b;否则 和保持原值&#xff0c;循环完所有i&#xff0c;j后更新数组并且…

材料表面缺陷检测系统源码分享 # [一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]

材料表面缺陷检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

【rk3588】环境搭建及系统编译

开发板&#xff1a;ROC-RK3588S-PC 官方链接&#xff1a;Welcome to ROC-RK3588S-PC Manual — Firefly Wiki (t-firefly.com) 串口调试配置 一、产品介绍 — Firefly Wiki (t-firefly.com)&#xff0c;可以按照官方链接的说明在个人PC上使用串口。这个串口会输出rk3588的日…

字典查找对应输入的字符

一、将文件放入到数据库 #include<stdio.h> #include<sqlite3.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> int main(int agrc,char *agrv[]) {FILE *fp;fp fope…

详细介绍校园网络拓扑结构设计图

目录 需求分析 网络架构设计 拓扑图设计 安全策略 出口设计 总结 校园网络拓扑结构设计是一种对学校内计算机、网络设备和软件进行集成应用的系统化设计&#xff0c;旨在为师生提供一个高效、稳定、安全的网络平台&#xff0c;以支持教学、科研和管理的信息化需求。一个优…