当前位置: 首页 > news >正文

【数据结构与算法】数据结构初阶:排序内容加餐(二)——文件归并排序思路详解(附代码实现)


🔥个人主页:艾莉丝努力练剑

❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题

🍉学习方向:C/C++方向

⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平


这个用来测试代码的对比排序性能的代码博主依然还是附在下面,大家可以对比一下各种排序算法的运行时间,从而对不同排序方法的时间复杂度有更加直观地认识:

//测试排序的性能对比  
void TestOP()
{srand(time(0));const int N = 100000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);int* a3 = (int*)malloc(sizeof(int) * N);int* a4 = (int*)malloc(sizeof(int) * N);int* a5 = (int*)malloc(sizeof(int) * N);int* a6 = (int*)malloc(sizeof(int) * N);int* a7 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; ++i){a1[i] = rand();a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];a6[i] = a1[i];a7[i] = a1[i];}//begin和end的时间差就是int begin1 = clock();InsertSort(a1, N);int end1 = clock();int begin2 = clock();ShellSort(a2, N);int end2 = clock();int begin3 = clock();SelectSort(a3, N);int end3 = clock();int begin4 = clock();HeapSort(a4, N);int end4 = clock();int begin5 = clock();QuickSort(a5, 0, N - 1);int end5 = clock();int begin6 = clock();MergeSort(a6, N);int end6 = clock();int begin7 = clock();BubbleSort(a7, N);int end7 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("QuickSort:%d\n", end5 - begin5);printf("MergeSort:%d\n", end6 - begin6);printf("BubbleSort:%d\n", end7 - begin7);free(a1);free(a2);free(a3);free(a4);free(a5);free(a6);free(a7);
}

前言:本篇文章,我们继续来介绍排序相关拓展的加餐部分的知识点,在初阶的数据结构与算法阶段,我们把知识点分成三部分,复杂度作为第一部分,顺序表和链表、栈和队列、二叉树为第二部分,排序为第二部分,我们之前已经介绍完了第一部分:算法复杂度和第二部分:顺序表和链表、栈和队列、二叉树。本文我们继续学习第三部分中的排序的内容。


 


目录

正文

一、文件归并排序思路

1、了解外排序

2、文件归并排序的思路 

二、文件归并排序代码实现

结尾


正文

本文和上一篇文章属于是加餐,大家先掌握排序的主线内容再来看这些比较好。

先掌握排序数据结构的主线内容——插入排序、选择排序、交换排序、归并排序——再来看加餐。

上篇文章链接放在这里,当然结尾照例也挂了链接:

【数据结构与算法】数据结构初阶:排序内容加餐(一)——快速排序:三路划分、自省排序【数据结构与算法】数据结构初阶:排序内容加餐(一)——快速排序:三路划分、自省排序

一、文件归并排序思路

1、了解外排序

2、文件归并排序的思路 

画图理解: 

二、文件归并排序代码实现

以下是文件归并排序代码实现——

代码实现:

#define  _CRT_SECURE_NO_WARNINGS  1
#include<stdio.h>
#include<time.h>
#include<stdlib.h>//创建N个随机数,写到文件中
void CreatNData()
{//造数据int n = 10000000;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 compare(const void* a, const void* b)
{return(*(int*)a - *(int*)b);
}//返回实际读到的数据个数,没有数据了返回0
int ReadNDataSortToFile(FILE* fout, int n, const char* file1)
{int x = 0;int* a = (int*)malloc(sizeof(int) * n);if (a == NULL){perror("malloc error");return 0;}//想读取n个数据,如果遇到文件结束,应该读到j个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);FILE* fin = fopen(file1, "w");if (fin == NULL){free(a);perror("fopen error");return 0;}//写回file1文件for (int i = 0; i < j; i++){fprintf(fin, "%d\n", a[j]);}free(a);fclose(fin);return j;
}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", &x1);int ret2 = fscanf(fout2, "%d", &x2);while (ret1 != EOF && ret2 != EOF){if (x1 < x2){fprintf(mfin, "%d\n", x1);ret1 = fscanf(fout1, "%d", &x1);}else{fprintf(mfin, "%d\n", x2);ret2 = fscanf(fout2, "%d", &x2);}}while (ret1 != EOF){fprintf(mfin, "%d\n", x1);ret1 = fscanf(fout1, "%d", &x1);}while (ret2 != EOF){fprintf(mfin, "%d\n", x2);ret2 = fscanf(fout2, "%d", &x2);}fclose(fout1);fclose(fout2);fclose(mfin);
}int main()
{CreatNData();const char* file1 = "file1.txt";const char* file2 = "file1.txt";const char* mfile = "file1.txt";FILE* fout = fopen("data.txt", "r");if (fout == NULL){perror("fopen error");return;}int m = 1000000;ReadNDataSortToFile(fout, m, file1);ReadNDataSortToFile(fout, m, file2);while (1){MergeFile(file1, file2, mfile);//删除file1和file2remove(file1);remove(file2);//重命名mfile为file1rename(mfile, file1);//当再去读取数据,一个都读不到,说明此时已经没有数据了//已经归并完成,归并结果在file1int n = 0;if ((n = ReadNDataSortToFile(fout, m, file2)) == 0)break;//if (n < 100)//{//	int x = 0;//}}return 0;
}

注意:下图这里的m不要看错,一定要擦亮眼睛,铸币博主没注意,在这里写了个100,1000000个数据跑得那速度让铸币主包怀疑自己的电脑被夺舍了,主包还以为1946年那台世界上第一台计算机“埃尼阿克”的幽灵把主包电脑摄魂了,没想到是主包一开始测试的时候在这里写了个100忘记改掉了。。。大家不要犯跟博主一样的错误。


结尾

往期回顾:

【数据结构与算法】数据结构初阶:排序内容加餐(一)——快速排序:三路划分、自省排序【数据结构与算法】数据结构初阶:排序内容加餐(一)——快速排序:三路划分、自省排序

本期内容需要回顾的C语言知识如下面的截图中所示(指针博主写了6篇,列出来有水字数嫌疑了,就只放指针第六篇的网址,博主在指针(六)把指针部分的前五篇的网址都放在【往期回顾】了,点击【传送门】就可以看了)。

大家如果对前面部分的知识点印象不深,可以去上一篇文章的结尾部分看看,博主把需要回顾的知识点相关的博客的链接都放在上一篇文章了,上一篇文章的链接博主放在下面了:

【数据结构与算法】数据结构初阶:详解顺序表和链表(三)——单链表(上)

结语:本篇文章到这里就结束了,对数据结构的排序知识感兴趣的友友们可以在评论区留言,博主创作时可能存在笔误,或者知识点不严谨的地方,大家多担待,如果大家在阅读的时候发现了行文有什么错误欢迎在评论区斧正,再次感谢友友们的关注和支持! 

http://www.lryc.cn/news/608959.html

相关文章:

  • 【LeetCode 热题 100】84. 柱状图中最大的矩形——(解法一)单调栈+三次遍历
  • 二叉树的锯齿形层次遍历
  • 9.苹果ios逆向-FridaHook-ios中的算法(CCCrypt)
  • CCF-GESP 等级考试 2025年6月认证C++一级真题解析
  • wordpress登陆前登陆后显示不同的顶部菜单
  • 最简单的零基础软件测试学习路线
  • Libevent(5)之使用教程(4)工具
  • k8s黑马教程笔记
  • 快速搭建一个非生产k8s环境
  • 【运维基础】Linux 硬盘分区管理
  • k8s+isulad 国产化技术栈云原生技术栈搭建4-添加worker节点
  • Hyper-V + Centos stream 9 搭建K8s集群(二)
  • k8s+isulad 国产化技术栈云原生技术栈搭建3-master节点安装
  • [硬件电路-148]:数字电路 - 什么是CMOS电平、TTL电平?还有哪些其他电平标准?发展历史?
  • Go语言实战案例:TCP服务器与客户端通信
  • 案例介绍|JSON数据格式的转换|pyecharts模块简介
  • Kafka——怎么重设消费者组位移?
  • 构建企业级Web应用:AWS全栈架构深度解析
  • AtCoder Beginner Contest 417
  • [硬件电路-147]:模拟电路 - DC/DC电压的三种架构:升压(Boost)、降压(Buck)或升降压(Buck-Boost)
  • 跨语言模型中的翻译任务:XLM-RoBERTa在翻译任务中的应用
  • 界面规范4-按钮
  • IntelliJ IDEA开发编辑器摸鱼看股票数据
  • Parcel 使用详解:零配置的前端打包工具
  • 关于车位引导及汽车乘梯解决方案的专业性、系统性、可落地性强的综合设计方案与技术实现说明,旨在为现代智慧停车楼提供高效、安全、智能的停车体验。
  • electron-多线程
  • 嵌入式——数据结构:单向链表的函数创建
  • 常见的深度学习模块/操作中的维度约定(系统性总结)
  • Docker-03.快速入门-部署MySQL
  • 介绍JAVA语言、介绍greenfoot 工具