外部排序之文件归并

2024-09-02 06:36
文章标签 归并 排序 外部

本文主要是介绍外部排序之文件归并,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概述

外部排序(External Sorting)是一种用于处理无法完全加载到内存中的大量数据的排序技术。由于内存的限制,传统的内存排序算法(如快速排序、归并排序)可能无法处理超大规模的数据集合。因此,需要采用外部排序技术,将数据分割成较小的块,利用磁盘进行排序。

文件归并

概念

文件归并(File Merging)是一种将多个已排序文件合并成一个单一排序文件的过程。这通常用于处理大规模数据集,其中数据已经被分割成多个部分,每部分在内存中排序后存储在磁盘上。

实现思路

(1)读取n个值排序后写入file1,再读取n个值排序后写入file2

(2)file1和file2利用归并排序的思想,依次读取比较,取小的数尾插到mfile,mfile再归并为一个有序文件
在这里插入图片描述
(3)重命名mfile为file1,再次从data中读取n个数据排序后写入file2
(4)重复步骤2、3直到data无法读出数据,得到排序好的文件file1
在这里插入图片描述

代码实现

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
//创建随机数据
void CreateDate()
{int n = 40000;//生成随机数据(自1970年1月1日)srand(time(0));//常量字符指针 用file存储文件名的字符串const char* file = "data.txt";//对file文件进行写操作FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");//打印错误信息return;}//生成n个随机数并写入文件for (int i = 0; i < n; i++){int x = rand() + i;//添加换行符——保持数据完整性,方便读入fscanffprintf(fin, "%d\n", x);}fclose(fin);
}int compare(const void* a, const void* b)
{return (*(int*)a - *(int*)b);
}//传入file的实参,无需每次打开file文件,直接读出n个数据到file1
int ReadNDateSortToFile(FILE* fout,int n,const char* file1)
{//创建空间为n的数组int* a = (int*)malloc(sizeof(int) * n);if (a == NULL){perror("malloc fail");return 0;}int x = 0;//如果遇到文件读取结束,实际读取的数据为j个int j = 0;for (int i = 0; i < n; i++){//从fout读出一个数据赋值给x//如果读不出来说明data中数据读取完成if (fscanf(fout, "%d", &x) == EOF)break;a[j++] = x;}if (j == 0){free(a);return 0;}//内部排序(随意选择一种排序方法)qsort(a, j, sizeof(int), compare);//对file1文件进行写操作FILE* fin = fopen(file1, "w");if (fin == NULL){perror("fopen error");//打印错误信息return 0;}for (int i = 0; i < j; i++){fprintf(fin, "%d\n", a[i]);}free(a);fclose(fin);return j;//返回实际读到的数据个数,没有数据了返回0
}void MergeFile(const char* file1, const char* file2, const char* mfile)
{FILE* fout1 = fopen(file1, "r");if (fout1 == NULL){perror("fopen error");//打印错误信息return;}FILE* fout2 = fopen(file2, "r");if (fout2 == NULL){perror("fopen error");//打印错误信息return;}FILE* mfin = fopen(mfile, "w");if (mfin == NULL){perror("fopen error");//打印错误信息return;}//归并操作int x1 = 0;int x2 = 0;int ret1 = fscanf(fout1, "%d\n", &x1);int ret2 = fscanf(fout2, "%d\n", &x2);while (ret1 != EOF && ret2 != EOF){if (x1 < x2){fprintf(mfin, "%d\n", x1);ret1 = fscanf(fout1, "%d\n", &x1);}else{fprintf(mfin, "%d\n", x2);ret2 = fscanf(fout2, "%d\n", &x2);}}while (ret1 != EOF){fprintf(mfin, "%d\n", x1);ret1 = fscanf(fout1, "%d\n", &x1);}while (ret2 != EOF){fprintf(mfin, "%d\n", x2);ret2 = fscanf(fout2, "%d\n", &x2);}fclose(fout1);fclose(fout2);fclose(mfin);
}int main()
{CreateDate();const char* file1 = "file1.txt";const char* file2 = "file2.txt";const char* mfile = "mfile.txt";//对fout文件进行写操作FILE* fout = fopen("data.txt", "r");if (fout == NULL){perror("fopen error");//打印错误信息return 0;}ReadNDateSortToFile(fout,100,file1);ReadNDateSortToFile(fout, 100, file2);//文件归并while (1){MergeFile(file1, file2, mfile);//删除file1和file2remove(file1);remove(file2);//重命名mfile为file1rename(mfile, file1);//读入100个数据排序后到file2if (ReadNDateSortToFile(fout, 100, file2) == 0)break;}return 0;
}

这篇关于外部排序之文件归并的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

Java -jar命令如何运行外部依赖JAR包

《Java-jar命令如何运行外部依赖JAR包》在Java应用部署中,java-jar命令是启动可执行JAR包的标准方式,但当应用需要依赖外部JAR文件时,直接使用java-jar会面临类加载困... 目录引言:外部依赖JAR的必要性一、问题本质:类加载机制的限制1. Java -jar的默认行为2. 类加

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb

Java List排序实例代码详解

《JavaList排序实例代码详解》:本文主要介绍JavaList排序的相关资料,Java排序方法包括自然排序、自定义排序、Lambda简化及多条件排序,实现灵活且代码简洁,文中通过代码介绍的... 目录一、自然排序二、自定义排序规则三、使用 Lambda 表达式简化 Comparator四、多条件排序五、

JAVA数组中五种常见排序方法整理汇总

《JAVA数组中五种常见排序方法整理汇总》本文给大家分享五种常用的Java数组排序方法整理,每种方法结合示例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录前言:法一:Arrays.sort()法二:冒泡排序法三:选择排序法四:反转排序法五:直接插入排序前言:几种常用的Java数组排序

C#通过进程调用外部应用的实现示例

《C#通过进程调用外部应用的实现示例》本文主要介绍了C#通过进程调用外部应用的实现示例,以WINFORM应用程序为例,在C#应用程序中调用PYTHON程序,具有一定的参考价值,感兴趣的可以了解一下... 目录窗口程序类进程信息类 系统设置类 以WINFORM应用程序为例,在C#应用程序中调用python程序

Mybatis 传参与排序模糊查询功能实现

《Mybatis传参与排序模糊查询功能实现》:本文主要介绍Mybatis传参与排序模糊查询功能实现,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、#{ }和${ }传参的区别二、排序三、like查询四、数据库连接池五、mysql 开发企业规范一、#{ }和${ }传参的

C++快速排序超详细讲解

《C++快速排序超详细讲解》快速排序是一种高效的排序算法,通过分治法将数组划分为两部分,递归排序,直到整个数组有序,通过代码解析和示例,详细解释了快速排序的工作原理和实现过程,需要的朋友可以参考下... 目录一、快速排序原理二、快速排序标准代码三、代码解析四、使用while循环的快速排序1.代码代码1.由快

spring-boot-starter-thymeleaf加载外部html文件方式

《spring-boot-starter-thymeleaf加载外部html文件方式》本文介绍了在SpringMVC中使用Thymeleaf模板引擎加载外部HTML文件的方法,以及在SpringBoo... 目录1.Thymeleaf介绍2.springboot使用thymeleaf2.1.引入spring

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常