【数据结构】—超级详细的归并排序(含C语言实现)

                                       食用指南:本文在有C基础的情况下食用更佳 

                                       🔥这就不得不推荐此专栏了:C语言

                                       ♈️今日夜电波:斜陽—ヨルシカ

                                                                0:30━━━━━━️💟──────── 3:20
                                                                    🔄   ◀️   ⏸   ▶️    ☰ 

                                      💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


目录

♉️一、前置知识—什么是归并排序

 ♊️二、归并排序

        归并排序的思想

        归并排序的递归实现

       ♒️归并排序的非递归实现(难点)

♋️三、归并排序的特性总结


♉️一、前置知识—什么是归并排序

        归并排序是一种基于分治思想的排序算法。它将待排序的数组分成两个子数组,对每个子数组进行排序,最后将子数组合并成一个有序的数组。具体来说,归并排序采用递归的方式将数组不断二分,直到每个子数组只有一个元素,然后再将相邻的两个子数组归并成一个有序的数组,然后不断合并,直到最终得到原数组的有序排列,当然你也可以采用非递归的方法,总体的思路都是一样的。与快速排序不同的是,归并排序在每轮排序中都会将数组完全拆分成两个子数组。


 ♊️二、归并排序

        归并排序的思想

        归并排序是基于分治思想的一种排序算法,它可以将一个大问题分解成若干个小问题,再通过合并小问题的解来得到大问题的解。

        具体来说,归并排序的思想如下:

  1. 将待排序的数组划分为两个子数组,对每个子数组进行递归排序;
  2. 将排好序的子数组合并成一个有序的数组。

        这一过程可以不断重复,直到将整个数组划分为单个元素的子数组,然后再将其合并成一个有序数组,排序完成。

        一图理解~ 

        动图了解~ 

 

        归并排序的递归实现

        归并排序的递归实现步骤如下:

  1. 如果数组长度为1,直接返回该数组;
  2. 将数组按中间位置划分成两个子数组,分别对这两个子数组进行递归排序,得到排好序的两个子数组;
  3. 将排好序的两个子数组合并成一个有序数组,具体方法为创建一个辅助数组,同时遍历两个子数组,比较两个子数组中当前位置的元素,将较小的元素放入辅助数组中;
  4. 将辅助数组中的元素复制回原数组中。

        代码实现:

void _Mergesort(int* a, int* temp,int begin, int end)
{if (end <= begin)//递归结束条件return;int mid = (begin + end) / 2;//开始二分_Mergesort(a, temp, begin, mid);//左半边_Mergesort(a, temp, mid + 1, end);//右半边//正式的归并操作//分出来的两个数组的下标int begin1 = begin;int end1 = mid;int begin2 = mid + 1;int end2 = end;int index = begin;while(begin1 <= end1 && begin2 <= end2)//归并{if (a[begin1] < a[begin2]){temp[index++] = a[begin1++];}else{temp[index++] = a[begin2++];}}//当其中有一个条件不符合时,跳出循环,但是可能还有数据每遍历完while (begin1 <= end1){temp[index++] = a[begin1++];}while (begin2 <= end2){temp[index++] = a[begin2++];}// 拷贝回原数组memcpy(a + begin, temp + begin, (end - begin + 1) * sizeof(int));//拷贝对应的数据到对应的位置}void Mergesort(int* a, int n)
{int* temp = (int*)malloc(sizeof(int) * n);if (temp == NULL){perror("malloc fail");return;}_Mergesort(a, temp,0,n-1);free(temp);
}

         ♒️归并排序的非递归实现(难点)

        归并排序的非递归实现,也称为迭代实现,采用的是自底向上的方式,

        步骤如下:

  1. 将原数组按照长度为1的子数组进行划分,每个子数组都是有序的;
  2. 将长度为1的有序子数组两两合并,得到长度为2的有序子数组;
  3. 重复以上步骤,直到得到一个完整有序的数组。

         代码实现:

void MergesortNonR(int* a, int n)
{int* temp = (int*)malloc(sizeof(int) * n);if (temp == NULL){perror("malloc fail");return;}//设置一个gap用于从间距为1开始(也就是最开始的归并),对于数组进行归并操作,然后归并完一遍后让gap*2继续归并,以此类推int gap = 1;while (gap < n)//gap停止的条件,实际上gap在n的一半时就已经排好了{for (int i = 0; i < n; i += 2 * gap){//首先分出要归并的数组int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;//以下是处理越界的情况,有些时候当数组会越界// 如果第二组不存在,这一组不用归并了if (begin2 >= n){break;}// 如果第二组的右边界越界,修正一下if (end2 >= n){end2 = n - 1;}//以下的操作就是和递归的操作相同的归并操作int index = i;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){temp[index++] = a[begin1++];}else{temp[index++] = a[begin2++];}}while (begin1 <= end1){temp[index++] = a[begin1++];}while (begin2 <= end2){temp[index++] = a[begin2++];}// 拷贝回原数组memcpy(a + i, temp + i, (end2 - i + 1) * sizeof(int));}gap *= 2;}free(temp);
}


♋️三、归并排序的特性总结

        1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的
        外排序问题。
        2. 时间复杂度:O(N*logN)
        3. 空间复杂度:O(N)
        4. 稳定性:稳定


                    感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       

                                                                         给个三连再走嘛~  

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

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

相关文章

vue项目 H5 动态设置浏览器标题

1&#xff0c;先将要展示的标题存本地 if (that.PromotionInfo.Title) {localStorage.setItem("AcTitle", that.PromotionInfo.Title)} 2,现在路由meta中设置标题&#xff0c;再在路由守卫中设置 import Vue from vue import Router from vue-router import prom…

新手程序员怎么接单?

程序员如何在自己年富力强的时候&#xff0c;最大化发挥自己的能力&#xff1f;将超能力转化为“钞能力”&#xff1f; 有人还在苦哈哈当老黄牛&#xff0c;一身使不完的牛劲&#xff0c;有人已经另辟蹊径&#xff0c;开创了自己的一片致富小天地。 接单找兼职&#xff0c;就…

4k、VR与万兆光网

“全光万兆”对VR意义重大。 pico4的分辨率 PICO 4 的单眼分辨率是 2160 2160&#xff0c;整体分辨率高达 4320 2160。这是一款高性能的 VR 一体机&#xff0c;采用了 2.56 英寸的 Fast-LCD 屏幕&#xff0c;最高可实现 90Hz 刷新率&#xff0c;还有 1200 PPI 和 20.6 PPD 的…

线性约束最小方差准则(LCMV)波束形成算法仿真

常规波束形成仅能使得主波束对准目标方向&#xff0c;从而在噪声环境下检测到目标&#xff0c;但无法对复杂多变的干扰做出响应&#xff0c;所以不能称之为真正意义上的自适应滤波。自适应阵列处理指的是采用自适应算法对空间阵列接收的混合信号进行处理&#xff0c;又可称为自…

Android---打开相机拍照

简单实现打开系统系统相机拍一张图片并显示在UI上&#xff0c;适用与个人主页头像的切换。 1. 添加权限。AndroidManifest.xml里添加使用相机的权限。 <uses-permission android:name"android.permission.CAMERA"/> 2. 布局。布局内容比较交单&#xff0c;一…

[Java | Web] JavaWeb——JSON与AJAX简介

目录 一、JSON 简介 1、什么是 JSON 2、JSON 的定义和访问 3、JSON 在 JS 中两种常用的转换方法 4、JSON 在 Java 中的使用 5、匿名内部类 二、AJAX 简介 1、什么是 AJAX 2、原生 JS 的 AJAX 请求示例 3、JQuery 中的 AJAX 请求 一、JSON 简介 1、什么是 JSON JSON…

解决SpringBoot3整合Druid的兼容性问题

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 背景概述 截止目前&#xff0c;Druid对于SpringBoot3的支持不够全面和友好&#xff1b;存在一些兼容性的问题&#xff0c;导致项目报错。 解决方案 在此&#xff0c;针对…

使用低代码实现一个表单页面 ------ XinBuilder

平台介绍 如果你不是一个前端开发&#xff0c;但是想要实现出一个前端页面。 那么就可以通过低代码的方式&#xff0c;拖拽和配置出你想要的页面。 而XinBuilder就是简单的一套低代码平台&#xff0c;你可以在上面拖拽出自己想要使用的组件并进行配置。使用方式也很简单。 这…

影刀自动化采集底层逻辑

hello,大家好&#xff0c;这里是【玩数据的诡途】 接上回 <我的影刀故事> 今天给大家介绍一下整个采集的底层逻辑&#xff0c;包括业务流程自动化也是基于这一套基础逻辑进行展开的&#xff0c;顺便带大家熟悉一下影刀&#xff0c;既然叫影刀系列了&#xff0c;那后续一些…

【100天精通Python】Day65:Python可视化_Matplotlib3D绘图mplot3d,绘制3D散点图、3D线图和3D条形图,示例+代码

1 mpl_toolkits.mplot3d 功能介绍 mpl_toolkits.mplot3d 是 Matplotlib 库中的一个子模块&#xff0c;用于绘制和可视化三维图形&#xff0c;包括三维散点图、曲面图、线图等。它提供了丰富的功能来创建和定制三维图形。以下是 mpl_toolkits.mplot3d 的主要功能和功能简介&am…

服务断路器_Resilience4j信号量隔离实现

POM引入依赖 <dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-bulkhead</artifactId><version>1.7.0</version> </dependency>信号量隔离修改YML文件 resilience4j:#信号量隔离bulkhead:ins…

支撑电动汽车规模化,特来电智能化升级群充产品

9月26日&#xff0c;中国领先的充电网生态运营商特来电重磅发布智能群充4.0产品&#xff0c;标志着特来电群充产品体系进一步升级&#xff0c;充电行业迎来更高质量、更高性能的设备与系统&#xff0c;充电网基础设施将更好地支撑大规模电动汽车的发展。 群充技术路线引领充电…

Element UI搭建首页导航和左侧菜单以及Mock.js和(组件通信)总线的运用

目录 前言 一、Mock.js简介及使用 1.Mock.js简介 1.1.什么是Mock.js 1.2.Mock.js的两大特性 1.3.Mock.js使用的优势 1.4.Mock.js的基本用法 1.5.Mock.js与前端框架的集成 2.Mock.js的使用 2.1安装Mock.js 2.2.引入mockjs 2.3.mockjs使用 2.3.1.定义测试数据文件 2…

程序员不得不知道的排序算法-上

目录 前言 1.冒泡排序 2.选择排序 3.插入排序 4.希尔排序 5.快速排序 6.归并排序 总结 前言 今天给大家讲一下常用的排序算法 1.冒泡排序 冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法&#xff0c;它重复地从待排序的元素中比较相邻的两个元素&a…

Java中的IO流的缓冲流

不爱生姜不吃醋⭐️ 如果本文有什么错误的话欢迎在评论区中指正 与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 &#x1f334;IO流体系结构&#x1f334;缓冲流1.提高效率的原理2.缓冲流的类型3.字符缓冲流两个特有方法 &#x1f334;总结 &#x1f334;IO流体系…

硬件系统工程师宝典(42)-----耦合电容如何布局?

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。 上篇我们说到了对时序有要求的系统中如何正确使用蛇形走线&#xff0c;可以增加信号的延时&#xff0c;符合系统的时序要求。今天来说说电容去耦的…

三、VXLAN静态方式实验举例

VXLAN静态方式实验举例 1.1、静态方式部署集中式网关1.1.1、VXLAN隧道建立1.1.2、MAC地址动态学习1.1.3、同子网已知单播报文转发1.1.4、同子网BUM报文转发1.1.5、跨子网报文转发1.1.6、配置VXLAN接入业务部署方式 1.2、配置举例&#xff0c;相同网段互通&#xff08;静态方式&…

(数组/字符串) 380. O(1) 时间插入、删除和获取随机元素 ——【Leetcode每日一题】

❓ 380. O(1) 时间插入、删除和获取随机元素 难度&#xff1a;中等 实现 RandomizedSet 类&#xff1a; RandomizedSet() 初始化 RandomizedSet 对象bool insert(int val) 当元素 val 不存在时&#xff0c;向集合中插入该项&#xff0c;并返回 true &#xff1b;否则&#x…

【Maven入门篇】(1)详细讲解Maven的安装报错解决

&#x1f38a;专栏【Maven入门篇】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【The truth that you leave】 &#x1f970;欢迎并且感谢大家指出我的问题 文章目录 &#x1f33a;Maven介绍⭐作用⭐官网 &#x1f384;maven安…

【C语言】文件操作(一)

前言 本篇博客讲解对文件的操作&#xff0c;包括打开&#xff0c;关闭操作。在下篇博客将讲解文件的读写。 文章目录 一、 什么是文件&#xff1f;1.1 用于存储数据1.2 文件类型1.3 文件名1.4 二进制文件和文本文件 二、文件的打开和关闭2.1 流和标准流2.2 文件指针2.3文件的打…