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

news2024/11/15 23:21:02

外排序介绍

外排序是指能够处理极大量数据的排序算法。通常来说,外排序处理的数据不能一次装入内存,只能放在读写较慢的外存储器(通常是硬盘)上。外排序通常采用的是⼀种“排序-归并”的策略。在排序阶段,先读入能放在内存中的数据量,将其排序输出到⼀个临时文件,依此进行,将待排序数据组织为多个有序的临时文件。然后在归并阶段将这些临时文件组合为⼀个大的有序文件,也即排序结果。
跟外排序对应的就是内排序,之前常见的排序,都是内排序,这些排序思想适应的是数据在内存中,支持随机访问。归并排序的思想不需要随机访问数据,只需要依次按序列读取数据,所以归并排序既是⼀个内排序,也是⼀个外排序。

创建随机数据文件的代码

void CreatData()
{
	int n = 100000;
	srand((unsigned int)time(NULL));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("foprn fail!");
		return;
	}
	for (int i = 0; i < n; i++)
	{
		int x = rand() % n + 1;
		fprintf(fin, "%d\n", x);
	}
	fclose(fin);
}

在这里插入图片描述

文件归并排序思路分析

  1. 读取n个值排序后写到file1,再读取n个值排序后写到file2
  2. file1file2利⽤归并排序的思想,依次读取比较,取小的尾插到mfilemfile归并为⼀个有序文件
  3. file1file2删掉,mfile重命名为file1
  4. 再次读取n个数据排序后写到file2
  5. 继续⾛file1file2归并,重复步骤2,直到文件中无法读出数据。最后归并出的有序数据放到了file1

在这里插入图片描述

文件归并排序代码实现

  • 创建随机数据文件的代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void CreatData()
{
	int n = 100000;
	srand((unsigned int)time(NULL));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("foprn fail!");
		return;
	}
	for (int i = 0; i < n; i++)
	{
		int x = rand()+i;
		fprintf(fin, "%d\n", x);
	}
	fclose(fin);
}
  • 取n个数据放入file1中,并进行排序
int compare(const void* a, const void* b)
{
	return (*(int*)a - *(int*)b);
}

int ReadNDataSortToFile(FILE* fout, int n, const char* file1)
{
	int x = 0;
	int* a = (int*)malloc(sizeof(int) * n);
	if (a == NULL)
	{
		perror("malloc fail!");
		return 0;
	}
	int j = 0;
	for (int i = 0; i < n; i++)
	{
		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)
	{
		free(a);
		perror("fopen fail!");
		return 0;
	}
	for (int i = 0; i < j; i++)
	{
		fprintf(fin, "%d\n", a[i]);
	}
	free(a);
	fclose(fin);
	return j;
}
  • file1file2合并成mfile
void MergeFile(const char* file1, const char* file2, const char* mfile)
{
	FILE* fout1 = fopen(file1, "r");
	if (fout1 == NULL)
	{
		perror("fopen fail!");
		return;
	}
	FILE* fout2 = fopen(file2, "r");
	if (fout1 == NULL)
	{
		perror("fopen fail!");
		return;
	}
	FILE* fin = fopen(mfile, "w");
	if (fin == NULL)
	{
		perror("fopen fail!");
		return;
	}

	int x1 = 0, x2 = 0;
	int ret1 = fscanf(fout1,"%d",&x1);
	int ret2= fscanf(fout2, "%d", &x2);
	while (ret1 != EOF && ret2 != EOF)
	{
		if (x1 < x2)
		{
			fprintf(fin,"%d\n",x1);
			ret1 = fscanf(fout1, "%d", &x1);
		}
		else
		{
			fprintf(fin, "%d\n", x2);
			ret2 = fscanf(fout2, "%d", &x2);
		}
	}
	while (ret1 != EOF)
	{
		fprintf(fin, "%d\n", x1);
		ret1 = fscanf(fout1, "%d", &x1);
	}
	while (ret2 != EOF)
	{
		fprintf(fin, "%d\n", x2);
		ret2 = fscanf(fout2, "%d", &x2);
	}
	fclose(fout1);
	fclose(fout2);
	fclose(fin);
}
  • 文件归并的主思路
int main()
{
	CreatData();
	const char* file1 = "file1.txt";
	const char* file2 = "file2.txt";
	const char* mfile = "mfile.txt";

	FILE* fout = fopen("data.txt", "r");
	if (fout == NULL)
	{
		perror("fopen fail!");
		return 0;
	}

	int m = 1000;
	ReadNDataSortToFile(fout, m, file1);
	ReadNDataSortToFile(fout, m, file2);

	while (1)
	{
		MergeFile(file1, file2, mfile);
		//删除file1和file2
		remove(file1);
		remove(file2);

		//将mfile改名为file1
		rename(mfile,file1);

		//若读不到数据则退出
		if (ReadNDataSortToFile(fout, m, file2) == 0)
			break;
	}
	return 0;
}

在这里插入图片描述

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

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

相关文章

【Kafka源码走读】消息生产者与服务端的连接过程

说明&#xff1a;以下描述的源码都是基于最新版&#xff0c;老版本可能会有所不同。 一. 查找源码入口 kafka-console-producer.sh是消息生产者的脚本&#xff0c;我们从这里入手&#xff0c;可以看到源码的入口&#xff1a; if [ "x$KAFKA_HEAP_OPTS" "x&qu…

Vue处理表格长字段显示问题

背景 有些单元个中会有比较长的内容&#xff0c;如果使用默认格式&#xff0c;会导致单元格的高度比较怪异&#xff0c;需要将超长的内容进行省略。 当前效果&#xff1a; 优化效果&#xff1a; 优化代码&#xff1a; 在内容多的单元格增加下面代码 <el-table-columnprop…

SAP成本核算-事前控制(标准成本核算)

一、BOM清单 1、BOM清单抬头 BOM用途:决定成本核算控制的依据 物料清单状态:决定成本核算控制的依据 基本数量:用于计算标准的用量 有效期:决定生产工单开单的日期范围,以及成本核算的日期范围 物料清单状态默认值后台配置:事务代码OS21 2、BOM清单行项目 有效期:决…

Java框架Shiro、漏洞工具利用、复现以及流量特征分析

Shiro流量分析 前言 博客主页&#xff1a; 靶场&#xff1a;Vulfocus 漏洞威胁分析平台 Shiro&#xff08;Apache Shiro&#xff09;是一个强大且灵活的开源安全框架&#xff0c;专为Java应用程序提供安全性解决方案。它由Apache基金会开发和维护&#xff0c;广泛应用于企业级…

Anolis os系统进入单用户模式重置密码

Anolis os系统进入单用户模式重置密码 1、重启计算机。 2、在启动时&#xff0c;当GRUB菜单出现时&#xff0c;按下任意键停止自动倒计时。 3、选择要启动的内核版本&#xff0c;然后按e键编辑启动参数。 4、找到以linux或linux16开头的行&#xff0c;通常这行包含了启动内核…

keepalived与lvs

1 lvs Linux服务器集群系统(一) -- LVS项目介绍 LVS&#xff08;Linux Virtual Server&#xff09;即Linux虚拟服务器,是一个基于Linux操作系统的虚拟服务器技术&#xff0c;用于实现负载均衡和高可用性。章文嵩&#xff0c;是中国国内最早出现的自由软件项目之一。 2 lvs发展…

Circuitjs 快捷键完全列表

对于常见组件, 反复通过菜单去选择也是比较繁琐的, 系统考虑到这一点, 也为那些常用组件添加了快捷键. 通过 菜单--选项--快捷键... 可以查看所有快捷键, 分配新的快捷键或调整现有的快捷键. 点开菜单时, 位于菜单右侧的那些字母即是对应的快捷键, 如下图所示: 注: 旧版本有, …

Debug-022-el-upload照片上传-整体实现回顾

前情概要&#xff1a; 最近业务里通过el-upload实现一个上传图片的功能&#xff0c;有一些小小的心得分享给各位。一方面是review一下&#xff0c;毕竟实现了很多细小的功能&#xff0c;还有这么多属性、方法&#xff08;钩子&#xff09;和碰到的问题&#xff0c;感觉小有成就…

Swing中如何实现快捷键绑定和修改

在许许多多市面上常见的桌面软件中, 可以使用快捷键操作&#xff0c; 比如像微信一样,使用AltA 可以打开截图窗口&#xff0c;如果不习惯于AltA按键时&#xff0c;还可以打开设置去修改。 如果在swing中也想实现一个快捷键绑定和修改的操作&#xff0c;那么应该如何操作&#…

《计算机操作系统》(第4版)第8章 磁盘存储器的管理 复习笔记

第8章 磁盘存储器的管理 一 、外存的组织方式 1. 连续组织方式(连续分配方式) (1)概述 ①定义 连续组织方式要求为每一个文件分配一组相邻接的盘块。磁盘空间的联系组织方式如图8-1所示。 ②记录方法 在目录项的“文件物理地址”字段中记录该文件第一个记录所在的盘块号和文件…

【Docker深入浅出】Docker引擎架构介绍

文章目录 一. docker引擎介绍1. Docker daemon&#xff1a;实现Docker API&#xff0c;通过API管理容器2. containerd&#xff1a;负责容器的生命周期3. runc&#xff1a;用于创建和启动容器 二. 启动容器的过程1. 启动过程2. docker daemon的维护不会影响到运行中的容器3. shi…

依靠 VPN 生存——探索 VPN 后利用技术

执行摘要 在这篇博文中,Akamai 研究人员强调了被忽视的 VPN 后利用威胁;也就是说,我们讨论了威胁行为者在入侵 VPN 服务器后可以用来进一步升级入侵的技术。 我们的发现包括影响 Ivanti Connect Secure 和 FortiGate VPN 的几个漏洞。 除了漏洞之外,我们还详细介绍了一组…

C语言试题(含答案解析)

单选 1.下面C程序的运行结果为&#xff08;&#xff09; int main(void) {printf("%d", B < A);return 0; }A.编译错误 B.1 C.0 D.运行错误 A’的ascii码值为65&#xff0c;‘B’的ascii码值为66&#xff0c;‘B’<‘A’是不成立的&#xff0c;返回0&#xf…

spring学习(1)

目录 一、是什么 二、IOC思想 2.1 IOC创建对象的方式 三、Spring的配置 3.1 别名 3.2 Bean的配置 3.3 import 四、DI依赖注入 4.1 构造器注入 4.2 Set方式注入【重点】 4.3 拓展方式注入 五、Bean的自动装配 5.1 byName自动装配 5.2 byType自动装配 5.3 注解实现…

Vue小知识大杂烩

一、Vue组件的三大部分&#xff1a;template、Script、Style template --> 组件的模板结构 写html的地方 注意&#xff1a;<template> 是 vue 提供的容器标签&#xff0c;只起到包裹性质的作用&#xff0c;它不会被渲染为真正的 DOM 元素。 script -> 组件的…

超声波清洗机什么牌子值得入手? 清洁力好的超声波清洗机推荐

对于眼镜佩戴人士而言&#xff0c;超声波清洗机无疑是清洁神器&#xff01;它凭借高频振动技术&#xff0c;能深入眼镜的每一细微处及手洗难以触及的缝隙&#xff0c;有效清除顽固污渍&#xff0c;不仅大幅提高清洁效率&#xff0c;而且清洁质量远胜传统方法。随着超声波清洗机…

Linux下快速搭建七日杀官方私人服务器教程

今天给大家分享一下七日杀的个人开服教程&#xff0c;本教程基于Linux系统开发&#xff0c;推荐有一定基础的小伙伴尝试&#xff01;如果你没有Linux的基础但实在想开的小伙伴可以根据以下教程一步步进行操作&#xff0c;后续这边也会上架对应视频操作 架设前准备&#xff1a; …

Redis篇三:在Ubuntu下安装Redis

文章目录 1. 安装Redis2. 更改Redis的IP3. 使用redis自带的客户端来连接服务器4. Redis的客户端介绍 1. 安装Redis sudo apt install redis2. 更改Redis的IP 刚安装的Redis的ip是一个本地环回的ip&#xff0c;也就是只能由当前主机上的客户端进行访问&#xff0c;跨主机就访问…

IO进程线程 0823作业

作业 创建子父进程&#xff0c;子进程将1.txt内容拷贝到2.txt中&#xff0c;父进程将3.txt内容拷贝到4.txt中。 #include <myhead.h> int main(int argc, const char *argv[]) {pid_t ID;ID fork();if(ID > 0){int fd1;fd1 open("./3.txt",O_RDONLY);if(…

js 键盘监听 组合键

今天分享如何快速实现js快捷键监听 所需环境&#xff1a; 浏览器js 实现目标 mac/win兼容&#xff0c;一套代码&#xff0c;多个平台支持快捷键监听/单按键监听事件是否冒泡可设置使用方式简单快速挂载与卸载4行代码实现组合键监听 代码原理 把键盘监听事件挂载在documen…