归并排序详解(递归与非递归)

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

一、递归实现归并排序

1.算法描述

● 把长度为n的输入序列分成两个长度近似为n/2([begin,mid]  [mid + 1,end] )的子序列

● 对这两个子序列再分别进行归并排序,将区间分解到不可在分为止

● 依次将两个排序好的子序列合并成一个最终的排序序列 

方法: 开辟新数组,用双指针选出两个子序列中的较小元素尾插在新数组中

 2.动图演示

3.核心步骤 

(1)图示

(2)思考

为什么要将区间拆分成[begin,mid]  [mid + 1,end] ?

上面介绍过我们的算法步骤是把长度为 n 的输入序列分成两个长度近似为 n/2 的子序列,在此前提下,除了分成[begin,mid]  [mid + 1,end]外,还有一种分法:[begin,mid-1] [mid,end],为什么不用这种分法?

mid = (begin + end)/2,所以mid是偶数

示例:用两种不同的分法分解区间[0,9]

当所要分解的区间是 [偶数,偶数],上述的两种分法都行得通,但是当区间是[偶数,偶数+1]的情况,[begin,mid-1] [mid,end]这种分法就行不通。

5.参考代码

void _MergeSort(int* arr, int* tmp, int begin, int end)
{if (begin >= end)return;int mid = (begin + end) / 2;//偶数//[begin,mid]  [mid+1,end] ——>[偶数,偶数] [偶数+1,偶数+1]_MergeSort(arr,tmp, begin, mid);_MergeSort(arr, tmp, mid + 1, end);//左右区间有序就可以归并了//归并int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int i = begin;while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] <= arr[begin2]){tmp[i++] = arr[begin1++];}else{tmp[i++] = arr[begin2++];}}//剩下的尾插在tmp数组while (begin1 <= end1){tmp[i++] = arr[begin1++];}while (begin2 <= end2){tmp[i++] = arr[begin2++];}//将一定长度的tmp复制到arr中memcpy(arr + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}
//归并
void MergeSort(int* arr, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail!");return;}_MergeSort(arr,tmp, 0, n - 1);free(tmp);tmp = NULL;
}

不同排序对一百万个随机数进行排序的效率: (毫秒)

二、非递归实现归并排序

1.算法描述

● gap表示每组归并的数据个数

● i 表示每组归并的起始位置

● 两层循环,一层循环用来归并数组中的数据,另一层扩大归并的数据个数

2.核心步骤

(1)图示

 (2)思考

为什么要归并一次拷贝一次?

● 如果整体拷贝,在上述的“第二组的都越界不存在”的情况下,虽然跳出循环,但在整体拷贝的时候还会把越界的部分拷贝回去

● 但如果归并一次拷贝一次,在“第二组的都越界不存在”的情况下,直接跳出循环,不会将越界的部分拷贝到数组中

3.参考代码 

//归并(非递归)
void MergeSortNonR(int* arr, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail!");return;}//gap表示每组要归并数据的个数int gap = 1;while (gap  < n){    //i表示每组归并的起始位置for (int i = 0; i < n; i += 2 * gap)//个数于区间的转化关系{//[bagin1,end1] [bagin2,end2]int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;//第二组的都越界不存在,那么第二组不用归并了,跳出循环if (begin2 > n)break;//第二组的begin2没越界,end2越界了,需要修正区间,再归并if (end2 > n)end2 = n - 1;//归并int j = i;while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] <= arr[begin2]){tmp[j++] = arr[begin1++];}else{tmp[j++] = arr[begin2++];}}//剩下的尾插在tmp数组while (begin1 <= end1){tmp[j++] = arr[begin1++];}while (begin2 <= end2){tmp[j++] = arr[begin2++];}//将一定长度的tmp复制到arr中//归并一次拷贝一次memcpy(arr + i, tmp + i, (end2 - i + 1) * sizeof(int));}gap *= 2;}free(tmp);tmp = NULL;
}

三、算法分析 

归并排序是一种稳定的排序方法。和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(N*logN),代价是需要额外的内存空间。

特性总结:

(1) 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在此版中的外排序问题

(2) 时间复杂度:O(N*logN)  相当于一个满二叉树

(3) 空间复杂度:O(N)  开辟了一个额外的数组

(4) 稳定性:稳定

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

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

相关文章

【6】图像分类部署

【6】图像分类部署 文章目录 前言一、将pytorch模型转为ONNX二、本地终端部署2.1. ONNX Runtime部署2.2. pytorch模型部署&#xff08;补充&#xff09; 三、使用flask的web网页部署四、微信小程序部署五、使用pyqt界面化部署总结 前言 包括将训练好的模型部署在本地终端、web…

【Android】自定义换肤框架01之皮肤包制作

前言 目前为止&#xff0c;市面上主流的安卓换肤方案&#xff0c;其实原理都是差不多的 虽然大多都号称一行代码集成&#xff0c;但其实想要做到完全适配&#xff0c;并不简单 这个系列&#xff0c;就是让大家从零开始&#xff0c;完全掌握这方面知识&#xff0c;这样才能对…

RabbitMq - Java客户端基础【简单案例 +Work模型】

目录 1、前置知识 1.1、AMQP怎么理解 1.2、Spring AMQP是什么 1.3、为什么要了解Spring-AMQP&#xff1f; 2、使用Spring-AMQP实现一个发消息案例 3、Work模型 问题&#xff1a; 优化&#xff1a; 小结&#xff1a;Work模型的使用&#xff1a; 1、前置知识 1.1、AMQP怎…

【WPF】桌面程序开发之xaml页面基础布局方式详解

使用Visual Studio开发工具&#xff0c;我们可以编写在Windows系统上运行的桌面应用程序。其中&#xff0c;WPF&#xff08;Windows Presentation Foundation&#xff09;项目是一种常见的选择。然而&#xff0c;对于初学者来说&#xff0c;WPF项目中xaml页面的布局设计可能是一…

EtherCAT转Profinet网关配置说明第三讲:博图配置

EtherCAT协议转Profinet协议网关模块&#xff08;XD-ECPNS20&#xff09;是实现EtherCAT协议和Profinet协议之间无缝通讯的重要设备。使EtherCAT协议和Profinet协议能够相互转换&#xff0c;进行工控自动化里的互连和传送数据。 EtherCAT作为一种高性能实时以太网通信协议&…

【讲解下iOS语言基础】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【Linux详解】进程等待 | 非阻塞轮询

引入&#xff1a; 为什么&#xff1f;是什么&#xff1f;怎么办 是什么&#xff1f; 进程等待是指父进程暂停自己的执行&#xff0c;直到某个特定的子进程结束或发生某些特定的事件。 为什么&#xff1f; 僵尸进程刀枪不入&#xff0c;不可被杀死&#xff0c;存在内存泄露…

Linux_实现简易日志系统

目录 1、认识可变参数 2、解析可变参数 3、打印可变参数 3.1 va_list 3.2 va_start 3.3 va_arg 3.4 va_end 3.5 小结 4、实现日志 4.1 日志左半部分 4.2 日志右半部分 4.3 日志的存档归类 结语 前言&#xff1a; 在Linux下实现一个日志系统&#xff0c;该日…

ffmpeg图片视频编辑器工具的安装与使用

title: ffmpeg图片视频编辑器工具的安装与使用 tags: [ffmpeg, 图片, 音频, 视频, 工具, 流媒体] categories: [工具, ffmpeg] FFmpeg是一个开源的命令行工具&#xff0c;广泛用于处理视频和音频文件&#xff0c;包括转换格式、剪辑、混流、解码、编码等。以下是一些基本的FFmp…

java项目总结6

目录 1.双列集合 2.map的三种遍历方式&#xff1a; 1.键找值 2.键值对 3.lambda遍历map 3.HashMap 例子&#xff1a;统计字符出现次数 4.LinkedHashMap 5.TreeMap 6.可变参数 7.Collections: 1.双列集合 双列集合特点&#xff1a; 定义Map<String&#xff0c;St…

Linux中的管道符‘|‘以及SQL(DQL,DCL)

ls 指令 语法&#xff1a; ls [选项][目录或文件] 功能&#xff1a; 对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; -a 列出目录下的所有文件&#xff0c;包括以 . 开头的隐含文件。 -…

自注意力机制和多头注意力机制区别

Ref&#xff1a;小白看得懂的 Transformer (图解) Ref&#xff1a;一文彻底搞懂 Transformer&#xff08;图解手撕&#xff09; 多头注意力机制&#xff08;Multi-Head Attention&#xff09;和自注意力机制&#xff08;Self-Attention&#xff09;是现代深度学习模型&#x…

昇思25天学习打卡营第19天|Pix2Pix实现图像转换

1. 学习内容复盘 Pix2Pix概述 Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c;该模型是由Phillip Isola等作者在2017年CVPR上提出的&#xff0c;可以实现语义/标签到真实…

点胶系统实战1-项目介绍

准备实战开发如下图的多轴点胶系统实战课程&#xff0c;内容设计界面开发、运动板块开发、任务管理、点胶的控制等。我们将和进入这个领域的初学者门一起进步。 有感兴趣的小伙伴&#xff0c;可以关注点赞&#xff0c;或评论区反馈你们的重点关注的内容&#xff0c;那些部分我…

Postman使用指南①网页版使用

postman官网地址&#xff1a;Postman API Platform 进入后点击右上角免费注册&#xff0c;注册后登录 登录之后即可在网页使用&#xff0c;无需下载

线上问题---反思与回顾

线上问题一&#xff1a;麦哲伦2.0 人群配置不生效 发现背景&#xff1a;产品发现三层模型部分计划个别测试计划圈选人群特征与数仓统计数据的人群不一致&#xff0c;向值班人员反馈 根因定位&#xff1a; &#xff08;1&#xff09;用户配置三层模型计划时&#xff0c;配置单…

RNN 交叉熵

RNN善于处理时序 序列数据 简单RNN 展开就是 LSTM 遗忘门f_t决定上期记忆保留多少 隐藏层 在神经网络中&#xff0c;隐藏层指的是除了输入层和输出层之外的层&#xff0c;它们的输出不会直接用于网络的最终输出&#xff0c;而是作为中间步骤用于提取和转换数据。因此&#x…

【网络安全】实验五(身份隐藏与ARP欺骗)

一、本次实验的实验目的 &#xff08;1&#xff09;了解网络攻击中常用的身份隐藏技术&#xff0c;掌握代理服务器的配置及使用方法 &#xff08;2&#xff09;通过实现ARP欺骗攻击&#xff0c;了解黑客利用协议缺陷进行网络攻击的一般方法 二、搭配环境 打开三台虚拟机&#…

SQL Server特性

一、创建表 在sql server中使用create table来创建新表。 create table Customers( id int primary key identity(1,1), name varchar(5) ) 该表名为Customers其中包含了2个字段&#xff0c;分别为id&#xff08;主键&#xff09;以及name。 1、数据类型 整数类型&#xff…

Towards Accurate and Robust Architectures via Neural Architecture Search

基于网络架构搜索的准确性与鲁棒性结构研究 论文链接&#xff1a;https://arxiv.org/abs/2405.05502 项目链接&#xff1a;未开源 Abstract 为了保护深度神经网络免受对抗性攻击&#xff0c;对抗性训练因其有效性而受到越来越多的关注。然而&#xff0c;对抗训练的准确性和鲁…