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

【排序算法】归并排序

目录

一.基本思想

二.递归版本

三.非递归版本

四.特性总结

1.时间复杂度:O(N*logN)

2.空间复杂度:O(N)

3.稳定性:稳定


一.基本思想

归并排序是采用分治法的一个非常典型的应用。它将已经有序的序列合并为完全有序的序列,即先使得每一个子序列有序,再让子序列之间有序。归并排序建立在归并操作上,以下动图能很好的演示归并排序中归并的过程:

但上图只展示了归并排序中归并的过程,没有对拆分过程的展示,接下来我将具体介绍归并排序的核心步骤。

已知对于两个已经有序的序列而言,使用p1和p2来比较,p1和p2中较小的一个一定就是当前最小的,放入临时数组tmp中,随后指向的p向后移动,再次进行比较,如此就能将两个有序的序列合并为一个有序序列,这就做到了排序。

然而,如何得到两个已经有序的序列呢?这是类似问题,与排序整个序列的主问题是类似的,很明显,已经可以猜到要使用递归来实现了,那么只需要将两个无序序列进行再次拆分,直到序列中仅剩一个数据,那么此时就可以看作是有序的了,这就是拆分过程。 

拆分结束后,就进行归并,每两个已有序的序列合并到一起,再和其他已合并的序列进行合并,最终合并为一个序列,这就是排序后得到的最终结果,下图展示了整个过程:

 具体应该如何拆分?拆分也是有讲究的,不注意会产生问题。一般都会想到取中分割,取序列左端为begin,右端为end,mid自然等于(begin+end)/2,那么就可以围绕mid拆分为左右两个序列,其中mid应该包含在左端,否则会造成死循环,也就是应该分为[begin,mid]和[mid+1,end],证明如下:

二.递归版本

//归并排序-主体
void _Merge(int* a, int* tmp, int begin, int end)
{//结束条件if (begin >= end)return;//拆分int mid = (begin + end) / 2;_Merge(a, tmp, begin, mid);_Merge(a, tmp, mid + 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, (end - begin + 1) * sizeof(int));
}//归并排序
void Merge(int* a, int n)
{//创建临时数组int* tmp = (int*)malloc(sizeof(int) * n);_Merge(a, tmp, 0, n - 1);free(tmp);tmp = NULL;
}

三.非递归版本

对于非递归版本,就不用考虑拆分的过程了,直接将一个数组看作单个有序的状态开始归并。使用gap来模拟归并的过程,如下所示:

根据上述过程可以得到以下代码,但这样的写法却存在一些问题 ,不妨打印出来看看

//归并排序-主体-(非递归)
void Merge_NonR(int* a, int n)
{//创建临时数组int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}//gap控制每组归并的数据个数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 + gap * 2 - 1;printf("[%d %d],[%d,%d]", begin1, end1, begin2, end2);int j = i;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 (begin2 <= end2){tmp[j++] = a[begin2++];}memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));}gap *= 2;printf("\n");}
}

 

可以很明显的看到,在只有10个数据的时候(有效下标为0到9),发生了数组越界的问题 ,那么这就还需要在程序中加入对应的解决方法,从上图可以发现,只要是begin2(上图的10和12)出现了越界(大于等于n)那么后一个序列就是非法的,也就不用归并了,此时可以直接跳出循环直接到下一个gap,那么到最后一轮,end2是越界的(如上图15)此时8到9是有序的,只需要调整end2为9(即n-1)即可。完整实现的代码如下:

//归并排序-主体-(非递归)
void Merge_NonR(int* a, int n)
{//创建临时数组int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}//gap控制每组归并的数据个数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 + gap * 2 - 1;if (begin2 >= n)break;if (end2 >= n)end2 = n - 1;printf("[%d %d],[%d,%d]", begin1, end1, begin2, end2);int j = i;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 (begin2 <= end2){tmp[j++] = a[begin2++];}memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));}gap *= 2;printf("\n");}
}

四.特性总结

1.时间复杂度:O(N*logN)

依据二分往下递归,类似于二叉树,总共有LogN层,每层总的归并合计起来可以看作O(N),因此总的时间复杂度可以看作是:O(N*logN)

2.空间复杂度:O(N)

由于开辟了一个大小为N的额外数组,因此归并排序的空间复杂度为O(N)

3.稳定性:稳定

相关文章:

【排序算法】归并排序

目录 一.基本思想 二.递归版本 三.非递归版本 四.特性总结 1.时间复杂度&#xff1a;O(N*logN) 2.空间复杂度&#xff1a;O(N) 3.稳定性&#xff1a;稳定 一.基本思想 归并排序是采用分治法的一个非常典型的应用。它将已经有序的序列合并为完全有序的序列&#xff0c;即…...

游戏AI的创造思路-技术基础-决策树(2)

上一篇写了决策树的基础概念和一些简单例子&#xff0c;本篇将着重在实际案例上进行说明 目录 8. 决策树应用的实际例子 8.1. 方法和过程 8.1.1. 定义行为 8.1.2. 确定属性 8.1.3. 构建决策树 8.1.4. 实施行为 8.1.5. 实时更新 8.2. Python代码 8. 决策树应用的实际例子…...

vue缓存页面,当tab切换时保留原有的查询条件

需求&#xff1a; 切换tab时&#xff0c;查询条件不变 路由页面&#xff1a; 单个页面上加这句话&#xff1a;...

PythonConda系列(亲测有效):【解决方案】Collecting package metadata (current_repodata.json): failed

【解决方案】Collecting package metadata (current_repodata.json&#xff09;: failed 问题描述解决方案小结参考文献 问题描述 在cmd下运行&#xff1a;conda install pylint -y&#xff0c;报错如下&#xff1a; C:\Users\apr> conda install --name apr pylint -y Co…...

web前端开发——标签一(注释、标题、段落、换行、格式、图片)

今天我来针对web前端开发讲解标签一 目录 html标签_标题&段落&换行 注释标签&#xff1a;Ctrl/ 标题标签&#xff1a; h1-h6 段落标签&#xff1a; 换行标签: 格式标签 图片标签_src属性 html标签_标题&段落&换行 注释标签&#xff1a;Ctrl/ Ctrl/ &…...

Django 常见的操作符

在filter() 方法&#xff0c;exclude() 方法中使用大于&#xff0c;小于&#xff0c;模糊匹配等操作符。 常见的操作符如下&#xff1a; 操作符含义示例等于Book.objects.filter(price10)! 或 __ne不等于用于查找字段不等于特定值的记录。但更常用exclude()方法。__gt大于用于…...

AJAX是什么?原生语法格式?jQuery提供分装好的AJAX有什么区别?

ajax 的全称 Asynchronous JavaScript and XML (异步 JavaScript 和 XML)。 AJAX是一种创建交互式网页应用的网页开发技术。其中最核心的依赖是浏览器提供的 XMLHttpRequest 对象&#xff0c;是这个对象使得浏览器可以发出 HTTP 请求与接收 HTTP 响应。实现了在页 面不刷新的…...

docker基础知识以及windows上的docker desktop 安装

记录以供备忘 基础概念&#xff1a; 什么是docker 将程序和环境一起打包&#xff0c;以在不同操作系统上运行的工具软件 什么是基础镜像 选一个基础操作系统和语言后&#xff0c;将对应的文件系统、依赖库、配置等打包为一个类似压缩包的文件&#xff0c;就是基础镜像 什么是…...

【深度学习基础】环境搭建 linux系统下安装pytorch

目录 一、anaconda 安装二、创建pytorch1. 创建pytorch环境&#xff1a;2. 激活环境3. 下载安装pytorch包4. 检查是否安装成功 一、anaconda 安装 具体的安装说明可以参考我的另外一篇文章【环境搭建】Linux报错bash: conda: command not found… 二、创建pytorch 1. 创建py…...

【Sql Server】sql server 2019设置远程访问,外网服务器需要设置好安全组入方向规则

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂》。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言1、无法链接…...

idea启动vue项目一直卡死在51%,问题分析及其如何解决

如果你的项目也一直卡在百分之几十&#xff0c;你可以参考下面的方法&#xff0c;试一试能否解决 问题描述&#xff1a; 通过在idea终端中输入命令 npm run serve 启动vue项目&#xff0c;启动进程一直卡在51% 如何解决&#xff1a; 检查 < template > 标签中的html内容…...

基于STM32设计的智能喂养系统(ESP8266+微信小程序)175

基于STM32设计的牛羊喂养系统(微信小程序)(175) 文章目录 一、前言1.1 项目介绍【1】项目功能介绍【2】项目硬件模块组成【3】ESP8266工作模式配置【4】上位机开发【5】项目模块划分1.2 项目功能需求1.3 项目开发背景1.4 开发工具的选择1.5 系统框架图1.6 系统原理图1.7 硬件实…...

第三方支付平台如何完美契合游戏行业?

在数字经济的浪潮中&#xff0c;游戏行业以其独特的魅力和创新能力&#xff0c;成为全球文化和经济交流的重要桥梁。然而&#xff0c;海外游戏商在进军中国市场时&#xff0c;常面临一系列难题。本文将通过一个故事案例&#xff0c;揭示第三方支付平台PASSTO PAY如何帮助海外游…...

计算机网络 5.6网桥与交换机

第六节 网桥与交换机 一、认识网桥 1.功能&#xff1a;连接两个具有相同或相似的网络结构的网络&#xff0c;解决网络之间距离太远问题&#xff0c;提高网络可靠性&#xff0c;还可以起过滤帧的作用而提高网络的性能。 2.适用场合&#xff1a;同构网。 3.特点&#xff1a; …...

CDH实操--集群卸载

作者&#xff1a;耀灵 1、停止正在运行的服务 a、控制台停止集群服务 b、控制台停止Cloudera Management Service c、命令行停止cm服务 systemctl stop cloudera-scm-agent #所有节点执行 systemctl stop cloudera-scm-server #cdh01节点执行2、主线并移除Parcles rm -r…...

5G RedCap调查报告

一、5G RedCap技术背景 5G RedCap(Reduced Capability缩写,轻量化5G),是3GPP标准化组织定义下的5G裁剪版本,是5G面向中高速率连接场景的物联网技术,它的能力介于5G NR(含eMBB和uRLLC)和LPWA(如LTE-M和NR-IoT)之间,如图1所示,是5G-A(5G Advanced)的关键技术之一。…...

模型(卷积、fc、attention)计算量 MAC/FLOPs 的手动统计方法

文章目录 简介背景为什么理解神经网络中的MAC和FLOPs很重要&#xff1f;资源效率内存效率能耗功耗效率 模型优化性能基准研究与发展 FLOPs 和 MACs 定义1. 全连接层 FLOPs 计算步骤 1&#xff1a;识别层参数步骤 2&#xff1a;计算 FLOPs 和 MACs步骤 3&#xff1a;总结结果使用…...

Git 删除包含敏感数据的历史记录及敏感文件

环境 Windows 10 Git 2.41.0 首先备份你需要删除的文件&#xff08;如果还需要的话&#xff09;&#xff0c;因为命令会将本地也删除将项目中修改的内容撤回或直接提交到仓库中&#xff08;有修改内容无法提交&#xff09; 会提示Cannot rewrite branches: You have unstaged …...

vue-tabs标签页引入其他页面

tabs页面 <template> <div class"app-container"> <el-tabs v-model"activeName" type"card" tab-click"handleClick"> <el-tab-pane label"套餐用户列表" name"first"> <user-list r…...

U-net和U²-Net网络详解

目录 U-Net: Convolutional Networks for Biomedical Image Segmentation摘要U-net网络结构pixel-wise loss weight U-Net: Going Deeper with Nested U-Structure for Salient Object Detection摘要网络结构详解整体结构RSU-n结构RSU-4F结构saliency map fusion module -- 显著…...

HighwayEnv完全指南:10分钟快速上手自动驾驶强化学习环境

HighwayEnv完全指南&#xff1a;10分钟快速上手自动驾驶强化学习环境 【免费下载链接】HighwayEnv A minimalist environment for decision-making in autonomous driving 项目地址: https://gitcode.com/gh_mirrors/hi/HighwayEnv HighwayEnv是一个轻量级的自动驾驶决…...

保姆级教程:用PHPStudy+红日靶场复现一次完整的内网渗透(从外网打到域控)

从零构建内网渗透实战&#xff1a;PHPStudy环境下的红日靶场攻防演练 在网络安全领域&#xff0c;内网渗透测试是检验企业防御体系完整性的重要手段。本文将带领读者使用常见的PHPStudy环境搭建红日靶场&#xff0c;通过模拟真实攻击路径&#xff0c;从外网Web渗透逐步深入内网…...

ANSYS模态分析后,如何用MATLAB把导出的HB格式刚度矩阵变回普通矩阵?(附完整命令流)

ANSYS模态分析后HB格式刚度矩阵的MATLAB转换全流程解析 在结构动力学和有限元分析领域&#xff0c;ANSYS与MATLAB的协同工作已经成为科研人员和工程师的标配工作流。模态分析作为结构动态特性研究的基础&#xff0c;其刚度矩阵的导出与后续处理尤为关键。然而&#xff0c;当您从…...

数据库优化:高效查询GUID的技巧

在日常的数据库操作中,如何高效地查询数据是一个永恒的话题。特别是当我们处理大型数据集和需要在文本字段中查找特定模式(如GUID)时,查询效率显得尤为关键。今天,我将分享一种优化查询GUID的方法,帮助你从长达数小时的查询时间中解脱出来。 背景 假设我们有一个数据库…...

OrigamiSimulator:3分钟上手实时折纸模拟的完整指南

OrigamiSimulator&#xff1a;3分钟上手实时折纸模拟的完整指南 【免费下载链接】OrigamiSimulator Realtime WebGL origami simulator 项目地址: https://gitcode.com/gh_mirrors/or/OrigamiSimulator 你是否曾经好奇复杂的折纸结构是如何从平面纸张变为立体形态的&…...

大模型小白入门指南:从工作原理到实用技巧(收藏版)

本文深入解析了大语言模型&#xff08;LLM&#xff09;的核心工作原理&#xff0c;包括Transformer架构的自注意力机制和位置编码&#xff0c;以及预训练和指令微调的训练范式。同时&#xff0c;文章还提供了实用的提示工程技巧&#xff0c;帮助读者更好地与AI协作。此外&#…...

利用快马平台快速构建技能评估系统原型:以skill-vetter为例

利用快马平台快速构建技能评估系统原型&#xff1a;以skill-vetter为例 最近在做一个前端开发技能评估系统&#xff0c;需要快速验证产品原型。传统开发流程从搭建环境到功能实现至少需要1-2周&#xff0c;但通过InsCode(快马)平台的AI辅助和现成模板&#xff0c;我只用了3天就…...

腾讯文档协作全攻略:从权限设置到区域锁定,团队办公效率翻倍

腾讯文档团队协作高阶指南&#xff1a;权限控制与区域锁定的艺术 在数字化办公时代&#xff0c;团队协作的效率往往决定了项目的成败。作为国内领先的在线协作文档工具&#xff0c;腾讯文档凭借其流畅的实时协作体验和丰富的权限管理功能&#xff0c;已经成为众多团队的首选工具…...

优化算法中的‘0.618’魔法:黄金分割法为何是工程优化的首选入门工具?

黄金分割法&#xff1a;从古希腊美学到现代工程优化的优雅解决方案 在工程优化领域&#xff0c;算法选择往往让初学者感到困惑。面对梯度下降、牛顿法等复杂方法&#xff0c;有一种源自公元前300年的数学比例——黄金分割比&#xff08;0.618&#xff09;&#xff0c;却成为了…...

别再为日期格式头疼了!Oracle TO_TIMESTAMP函数保姆级使用指南(含常见报错解决)

Oracle TO_TIMESTAMP实战&#xff1a;从混乱字符串到精准时间戳的避坑指南 刚接手一个数据迁移项目时&#xff0c;我对着几十万条格式各异的日期记录发愁——有"2023/12/01"这样的斜杠分隔&#xff0c;也有"01-Dec-23 14.30.00.123"带英文月份缩写和毫秒的…...