利用画图以及代码分析详细解读外排序的实现过程

news/2024/11/29 17:30:45/

外排序的实现

  • 思想
  • 代码分析
  • 完整代码

如果有海量数据需要排序,而在内存中放不下这么多数据,因此就不能使用内排序(直接插入排序,希尔排序,堆排序,快速排序,归并排序等等)。关于想了解这些内排序的请看这里各种排序的实现,所以我们只能使用外排序,来把我们海量数据排好序,

思想

外排序,我们需要采用归并排序的思想来实现这个过程。
在这里插入图片描述

因此我们最终思想是这样的
在这里插入图片描述

代码分析

要学会写外排序的代码,需要把文件学好,想了解文件的请看这里文件

假设文件里有100个数据
生成1-100个随机数放在文件里

#define N 100void CreteartFile(const char* filename)
{srand((unsigned int)time(NULL));//生成一个随机数1-100的文件FILE* pf = fopen(filename, "w");if (pf == NULL){perror("fopen fail");return;}for (int i = 0; i < N; ++i){fprintf(pf, "%d ", rand() % 100 + 1);}fclose(pf);}int  main()
{const char* filename = "Sort.txt";CreteartFile(filename);//外排序MerSortFile(filename);return 0;
}

把文件平均分成若干个有序的小文件

我们有一个100个数的文件
把这个文件平均分成10个小文件,每个小文件放10个数。
为了使这些小文件的数据有序,因此我们在大文件里取出数据,放在数组a中,只要数组a里的数据达到10个。就对数组a使用快排(假设内存可以一次放得下这么数据),直到取完文件中的数据。

//外排序
void MerSortFile(const char* filename)
{//取数据,把一个文件分成若干个有序的小文件FILE* fout = fopen(filename, "r");if (fout == NULL){perror("fopen fail");return;}int a[10] = { 0 };int value = 0;int i = 0;int n = 10;//存放小文件名称char fsubename[10] = { 0 };int fnumeber = 0;//从文件中取出数据while (fscanf(fout, "%d", &value) != EOF){//一个小文件放10个数据if (i < n-1){a[i++] = value;}else{//这里是特殊处理,下面画图有解释a[i] = value;//对a数组排序QuickSort(a, 0, n - 1);//创建小文件,并将a写到小文件里sprintf(fsubename, "%d.txt", ++fnumeber);FILE* fin = fopen(fsubename, "w");if (fin == NULL){perror("fopen fail");return;}//写数据for (int i = 0; i < n; ++i){fprintf(fin, "%d ", a[i]);}fclose(fin);i = 0;}}fclose(fout);
}

在这里插入图片描述
两两归并小文件,直到归并成一个文件

//外排序
void MerSortFile(const char* filename)
{//取数据,把一个文件分成若干个有序的小文件FILE* fout = fopen(filename, "r");if (fout == NULL){perror("fopen fail");return;}int a[10] = { 0 };int value = 0;int i = 0;int n = 10;char fsubename[10] = { 0 };int fnumeber = 0;while (fscanf(fout, "%d", &value) != EOF){//一个小文件放10个数据if (i < n-1){a[i++] = value;}else{a[i] = value;//对a数组排序QuickSort(a, 0, n - 1);//创建小文件,并将a写到小文件里sprintf(fsubename, "%d.txt", ++fnumeber);FILE* fin = fopen(fsubename, "w");if (fin == NULL){perror("fopen fail");return;}//写数据for (int i = 0; i < n; ++i){fprintf(fin, "%d ", a[i]);}fclose(fin);i = 0;}}//归并小文件,直到整体归成一个有序的完整文件//这一块逻辑看下图分析char mfile[20] = "12";char file1[20] = "1.txt";char file2[20] = { 0 };for (int i = 2; i <= n; ++i){sprintf(file2, "%d.txt", i);_MergerFile(mfile, file1, file2);//迭代,file1存储mfile名strcpy(file1, mfile);//mfile存储下一次两个文件要归并在一起的文件名sprintf(mfile, "%s%d", mfile, i+1);}fclose(fout);
}

在这里插入图片描述
两个小文件归并过程

void _MergerFile(const char* mfile,const char* file1,const char* file2)
{FILE* fin = fopen(mfile, "w");if (fin == NULL){perror("fopen fail");return;}FILE* fout1 = fopen(file1, "r");if (fout1 == NULL){perror("fopen fail");return;}FILE* fout2 = fopen(file2, "r");if (fout2 == NULL){perror("fopen fail");return;}int num1 = 0;int num2 = 0;
//这里也是对文件指针的特殊处理,看下图int ret1 = fscanf(fout1, "%d", &num1);int ret2 = fscanf(fout2, "%d", &num2);while (ret1 != EOF && ret2 != EOF){if (num1 < num2){fprintf(fin, "%d ", num1);ret1= fscanf(fout1, "%d", &num1);}else{fprintf(fin, "%d ", num2);ret2 = fscanf(fout2, "%d", &num2);}}while (ret1 != EOF){fprintf(fin, "%d ", num1);ret1 = fscanf(fout1, "%d", &num1);}while (ret2 != EOF){fprintf(fin, "%d ", num2);ret2 = fscanf(fout2, "%d", &num2);}fclose(fin);fclose(fout1);fclose(fout2);}

在这里插入图片描述

完整代码

//合并小文件
void _MergerFile(const char* mfile,const char* file1,const char* file2)
{FILE* fin = fopen(mfile, "w");if (fin == NULL){perror("fopen fail");return;}FILE* fout1 = fopen(file1, "r");if (fout1 == NULL){perror("fopen fail");return;}FILE* fout2 = fopen(file2, "r");if (fout2 == NULL){perror("fopen fail");return;}int num1 = 0;int num2 = 0;int ret1 = fscanf(fout1, "%d", &num1);int ret2 = fscanf(fout2, "%d", &num2);while (ret1 != EOF && ret2 != EOF){if (num1 < num2){fprintf(fin, "%d ", num1);ret1= fscanf(fout1, "%d", &num1);}else{fprintf(fin, "%d ", num2);ret2 = fscanf(fout2, "%d", &num2);}}while (ret1 != EOF){fprintf(fin, "%d ", num1);ret1 = fscanf(fout1, "%d", &num1);}while (ret2 != EOF){fprintf(fin, "%d ", num2);ret2 = fscanf(fout2, "%d", &num2);}fclose(fin);fclose(fout1);fclose(fout2);}//外排序
void MerSortFile(const char* filename)
{//取数据,把一个文件分成若干个有序的小文件FILE* fout = fopen(filename, "r");if (fout == NULL){perror("fopen fail");return;}int a[10] = { 0 };int value = 0;int i = 0;int n = 10;char fsubename[10] = { 0 };int fnumeber = 0;while (fscanf(fout, "%d", &value) != EOF){//一个小文件放10个数据if (i < n-1){a[i++] = value;}else{a[i] = value;//对a数组排序QuickSort(a, 0, n - 1);//创建小文件,并将a写到小文件里sprintf(fsubename, "%d.txt", ++fnumeber);FILE* fin = fopen(fsubename, "w");if (fin == NULL){perror("fopen fail");return;}//写数据for (int i = 0; i < n; ++i){fprintf(fin, "%d ", a[i]);}fclose(fin);i = 0;}}//归并小文件,直到整体归成一个有序的完整文件char mfile[20] = "12";char file1[20] = "1.txt";char file2[20] = { 0 };for (int i = 2; i <= n; ++i){sprintf(file2, "%d.txt", i);_MergerFile(mfile, file1, file2);strcpy(file1, mfile);sprintf(mfile, "%s%d", mfile, i+1);}fclose(fout);
}

http://www.ppmy.cn/news/104878.html

相关文章

小主机折腾记12 HP 285G3 PRO MT

五一期间&#xff0c;无事&#xff0c;咸鱼购入HP 285G3 PRO MT折腾 HP 285 PRO G3 MT准系统 150包邮 R5 2600 250包邮 金百达3200内存 229京东包邮 直接说准系统情况&#xff1a; 1.主机有三个sata接口&#xff0c;两个硬盘接口&#xff0c;一个光驱接口&#xff08;应该是可以…

web 前端技术体系大全(IT枫斗者)

web 前端技术体系大全 前端技术框架 Vue.js 官网&#xff1a;https://cn.vuejs.org/Vue CLI&#xff1a;https://cli.vuejs.org/菜鸟教程&#xff1a;http://www.runoob.com/w3cnote…Nuxt.js&#xff1a;https://zh.nuxtjs.org/桌面应用 Electron&#xff1a;https://elect…

2. JVM内存模型深度剖析与优化

JVM性能调优 1. JDK的体系结构2. Java语言的跨平台特性3.JVM整体结构及内存模型3.1 内存模型3.1.1 PC寄存器&#xff08;线程私有&#xff09;3.1.2 虚拟机栈&#xff08;线程私有&#xff09;1. 局部变量表2. 操作数栈 本文是按照自己的理解进行笔记总结&#xff0c;如有不正确…

数据结构与算法06:递归和简单的排序

目录 【递归】 【排序】 冒泡排序 插入排序 选择排序 【每日一练&#xff1a;K 个一组翻转链表】 【递归】 递归是将一些有规律的重复问题分解为同类的子问题的方法&#xff0c;也就是在函数中自己调用自己。比较经典的递归代码就是 斐波那契数列&#xff0c;实现方式如…

算法02-入门算法枚举与模拟算法

文章目录 总结大纲要求枚举算法枚举思想枚举举例题目描述 统计因数题目描述 质数判定错误方法一&#xff1a;优化方法1&#xff1a; 用break实现优化优化方法2&#xff1a; sqrt(n) 题目描述 水仙花数题目描述 7744问题实现方法1优化方法2 题目描述 余数相同问题题目描述 特殊自…

C++虚假唤醒

概念&#xff1a; 虚假唤醒是指在使用条件变量时&#xff0c;线程被唤醒但条件并没有满足&#xff0c;导致线程执行错误的情况&#xff0c;这个过程就是虚假唤醒。 虚假唤醒弊端&#xff1a; 虚假唤醒会导致程序的正确性受到影响&#xff0c;因为唤醒的线程并没有满足条件&…

SCI 投稿论文入门 —— 2. 图片编辑(Visio / Origin)

目录 引言IEEE trans论文图片格式要求单栏图片双栏图片 论文中插入曲线图曲线图具体要求 论文中插入结构图曲线图与结构图结合visio中设置界面单栏单张图片曲线图中需要插入结构图 箭头&#xff0c;线段粗细设置字体下标 引言 由于特殊要求&#xff0c;需要用word版本进行编辑…

Vue事件处理

1. 事件绑定 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width…