归并排序详解

目录

​💡基本思想

💡图文介绍

💡动图演示

💡过程解释

💡代码实现

💡递归实现

💡非递归实现 

💡总结


💡基本思想

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

💡图文介绍

💡动图演示

💡过程解释

分解为多个小区间

可以看到这种结构很像一棵完全二叉树,阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n。

合并相邻有序子序列

💡代码实现

💡递归实现

分割区间

以每个区间的中间位置为交界处,将一个区间分割为两个区间。

int mid = (begin + end) / 2;//[begin,mid] [begin+1,end]//先分再合并_MergeSort(a, begin, mid, tmp);_MergeSort(a, mid+1, end, tmp);

 返回条件

当区间内只剩下一个元素时,我们可以认为该区间是有序的。

if (begin >= end){return;}

 合并

  1. 合并是在分割完之后进行的,类似于二叉树里面的后序遍历,在递归的回归过程进行合并区间。
  2. 合并时,每次取较小的数尾插到tmp数组里
  3. 合并结束后,将tmp数组拷贝会原数组。
//[begin,mid] [begin+1,end]  归并int begin1 = begin, end1 = mid;int begin2 = mid+1, end2 = end;int i = begin;//合并两个有序数组//有一个到了终止条件就停止循环while (begin1 <= end1 && begin2 <= end2){if (a[begin1] <= a[begin2])//取小的尾插  相等时,取前一个尾插,这样就是稳定的{tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}//没循环完的直接尾插while (begin1 <= end1){tmp[i++] = a[begin1++];}while (begin2 <= end2){tmp[i++] = a[begin2++];}//拷贝回原数组memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));

 完整代码

void _MergeSort(int* a, int begin, int end,int* tmp)
{if (begin >= end){return;}int mid = (begin + end) / 2;//[begin,mid] [begin+1,end]//先分再合并_MergeSort(a, begin, mid, tmp);_MergeSort(a, mid+1, end, tmp);//[begin,mid] [begin+1,end]  归并int begin1 = begin, end1 = mid;int begin2 = mid+1, end2 = end;int i = begin;//合并两个有序数组//有一个到了终止条件就停止循环while (begin1 <= end1 && begin2 <= end2){if (a[begin1] <= a[begin2])//取小的尾插  相等时,取前一个尾插,这样就是稳定的{tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}//没循环完的直接尾插while (begin1 <= end1){tmp[i++] = a[begin1++];}while (begin2 <= end2){tmp[i++] = a[begin2++];}//拷贝回原数组memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}
//后序递归
void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc!");return;}_MergeSort(a, 0, n - 1, tmp);free(tmp);
}

💡非递归实现 

基本方法:

非递归的实现方法是采用一种顺序合并,就是直接以一个数作为一个区间,然后进行两两合并,一趟结束后,再以两个数作为一个区间,将区间两两合并,以此类推。

int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;//[begin1,end1][begin2,end2]

 注意:这种区间合并的方法可能会造成越界访问,所以我们需要加判断条件,又因为这里是在一趟合并结束后进行拷贝了,所以当begin2和end1大于等于n时,可以直接跳出这层循环,而当end2>=n时,则将end2=n-1,再进行合并。

//防止越界if (end1 >= n || begin2 >= n)break;if (end2 >= n){end2 = n - 1;//直接合并}

 完整代码

void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc!");return;}int gap = 1;while (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;//[begin1,end1][begin2,end2]//防止越界if (end1 >= n || begin2 >= n)break;if (end2 >= n){end2 = n - 1;//直接合并}printf("[%2d,%2d][%2d, %2d] ", begin1, end1, begin2, end2);int j = begin1;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}while (begin1 <= end1){tmp[j++] = a[begin1++];}while (j<n&&begin2 <= end2){tmp[j++] = a[begin2++];}memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));//防止越界拷贝}printf("\n");gap *= 2;}free(tmp);
}

💡总结

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

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

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

相关文章

数据结构--串

本文为复习的草稿笔记&#xff0c;&#xff0c;&#xff0c;有点乱 1. 串的基本概念和基本操作 串是由零个或多个字符组成的有限序列 2. 串的存储结构 3.串的应用 模式匹配 BF算法&#xff08;简单匹配算法 穷举法 算法思路&#xff1a;从子串的每一个字符开始依次与主串…

深耕文档型数据库12载,SequoiaDB再开源

1月15日&#xff0c;巨杉数据库举行SequoiaDB新特性及开源项目发布活动。本次活动回顾了巨杉数据库深耕JSON文档型数据库12年的发展历程与技术演进&#xff0c;全面解读了SequoiaDB包括在高可用、安全、实时、易用性四个方向的技术特性&#xff0c;宣布了2024年面向技术社区的开…

无法打开浏览器开发者工具的可能解决方法

网页地址: https://jx.xyflv.cc/?url视频地址url 我在抖音里面抓了一个视频地址, 获取到响应的json数据, 找到里面的视频地址信息 这个网站很好用: https://www.jsont.run/ 可以使用js语法对json对象操作, 找到所有视频的url地址 打开网页: https://jx.xyflv.cc/?urlhttps:…

【Linux C | 文件操作】目录相关操作 | mkdir、rmdir、opendir、readdir、closedir、getcwd、chdir

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

【LeetCode】栈精选9题

目录 1. 删除字符串中的所有相邻重复项&#xff08;简单&#xff09; 2. 逆波兰表达式&#xff08;中等&#xff09; 3. 基本计算器 II&#xff08;中等&#xff09; 4. 字符串解码&#xff08;中等&#xff09; 5. 验证栈序列&#xff08;中等&#xff09; 6. 小行星碰撞…

新能源汽车智慧充电桩方案:基于视频监控的可视化智能监管平台

一、方案概述 TSINGSEE青犀&触角云新能源汽车智慧充电桩方案围绕互联网、物联网、车联网、人工智能、视频技术、大数据、4G/5G等技术&#xff0c;结合云计算、移动支付等&#xff0c;实现充电停车一体化、充电桩与站点管理等功能&#xff0c;达到充电设备与站点的有效监控…

有效防范网络风险的关键措施

在数字化时代&#xff0c;企业面临着日益复杂和频繁的网络风险。提高员工的网络安全意识是防范网络威胁的关键一步。本文将探讨企业在提升网络安全意识方面可以采取的措施&#xff0c;以有效预防潜在的网络风险。 1. 开展网络安全培训&#xff1a;企业应定期组织网络安全培训&…

vue中内置指令v-model的作用和常见使用方法介绍以及在自定义组件上支持

文章目录 一、v-model是什么二、什么是语法糖三、v-model常见的用法1、对于输入框&#xff08;input&#xff09;&#xff1a;2、对于复选框&#xff08;checkbox&#xff09;&#xff1a;3、对于选择框&#xff08;select&#xff09;&#xff1a;4、对于组件&#xff08;comp…

java基本算法

1.链表 链表用来存储数据&#xff0c;由一系列的结点组成。这些结点的物理地址不一定是连续的&#xff0c;即可能连续&#xff0c;也可能不连续&#xff0c;但链表里的结点是有序的。一个结点由数据的值和下一个数据的地址组成。一个链表内的数据类型可以是多种多样的。数组也是…

中霖教育:2024年一建、二建考试问题整理

报名、考试时间&#xff1a; ①一建&#xff1a;报名时间6月;考试时间9月上旬 ②二建&#xff1a;报名时间1-3月份;考试时间6月 考试科目&#xff1a; ①一级建造师考试科目一共有四门,依次是《建设工程经济》、《建设工程法规及相关知识》、《建设工程项目管理》、《专业工…

Vue以弹窗形式实现导入功能

目录 前言正文 前言 由于个人工作原因&#xff0c;偏全栈&#xff0c;对于前端的总结还有些初出茅庐&#xff0c;后续会进行规整化的总结 对应的前端框架由&#xff1a;【vue】avue-crud表单属性配置&#xff08;表格以及列&#xff09; 最终实现的表单样式如下&#xff1a;…

深入浅出AI落地应用分析:国内Top10应用

接下来会每周集中体验一些通用或者垂直的AI落地应用&#xff0c;主要以一些全球或者国外国内排行较前的产品为研究对象&#xff0c;「AI 产品榜&#xff1a; aicpb.com」以专题的方式在博客进行分享。 1. 文心一言 产品链接&#xff1a;https://yiyan.baidu.com/ 产品介绍&…

UE5 C++ 学习笔记 UBT UHT 和 一些头文件

总结一些似懂非懂的知识点&#xff0c;从头慢慢梳理。 任何一个项目都有创建这些三个.cs。 这个是蓝图转C 这个是本身就是C项目,应该就是多了一个GameModeBase类 Build.cs包含了每个模块的信息&#xff0c;表明了这个项目用到了哪一些模块。该文件里的using UnrealBuilTool 是…

c JPEG 1D DCT

步骤&#xff1a; 1. 对yuv 88 数据 8行分别1D DCT 2, 用8行 1D DCT 得到的数据生成中间88 块 Zj 3,对Zj 的8列再 1D DCT 后生成8列,用这8列组合成8*8的2D DCT 系数 准备用此1D DCT程序代替以前写的2D DCT,看能减少多少编码时间。 看网上文章&#xff0c;ffmpeg用…

什么是车载信息娱乐系统和集成驾驶舱

什么是车载信息娱乐系统(IVI)? “车载信息娱乐(IVI)”通过向驾驶员和乘客提供信息和娱乐&#xff0c;为驾驶提供便利和舒适。为了理解这个概念&#xff0c;有必要知道“信息娱乐”的含义。“信息娱乐”是这个市场中使用的一个词&#xff0c;它结合了“信息”和“娱乐”两个词…

5.文本文件编辑命令

1.cat 用于查看纯文本文件&#xff08;内容较少的&#xff09; 加上-n参数&#xff0c;显示内容加行号 [rootlocalhost ~]# cat -n /etc/sysconfig/network-scripts/ifcfg-ens160 2.more 用于查看纯文本文件&#xff08;内容较多的&#xff09; 还可以使用空格键或回车 键…

使用pyechart创建折线图

import json from pyecharts.charts import Line from pyecharts import options# 首先使用文件打开数据 f_us open(Desktop/python/Project/数据可视化/美国.txt,r,encoding"UTF-8") f_rb open(Desktop/python/Project/数据可视化/日本.txt,r,encoding"UTF-8…

Springboot+vue项目部署所有遇到的坑

https://flowus.cn/siriusx/share/0a818075-372b-4948-88af-c75c1d10ceab项目地址及笔记 Spring Boot3VUE3前后端分离项目基于Jwt的校验方案 环境搭建 安装jdk17 安装mysql server https://ubuntu.com/server/docs/databases-mysql 将服务器root账号由系统验证改为密码验证…

SSL证书中RSA算法跟ECC算法的区别

RSA算法和ECC算法指的是SSL证书的加密算法&#xff0c;详细解释如下&#xff1a; RSA算法&#xff1a;国际标准算法&#xff0c;应用较早的算法之一&#xff0c;普遍性更强&#xff0c;同比ECC算法的适用范围更广&#xff0c;兼容性更好&#xff0c;一般采用2048位的加密长度&…