(排序7)归并排序(递归)

news2024/11/15 19:55:33

归并排序

  1. 归并排序采用的是两个有序数组的归并。比如说现在想让一个数组有序。之前我们讲过,如果说你现在有两个有序数组的话,那么我们就可以把这两个有序数组给他合并成一个有序数组。
  2. 两个有序区间归并的思路其实很简单(这个也是归并的单趟排序):就是把这两个有序区间从开头一直向后面,依次比较,小的尾插到新空间,是新空间。像链表用归并这个思想的话,他可以把那个节点给他“摘”下来,然后改动一下链接关系;但是如果对于数组要用归并思想的话,必须得借助一个新的空间。因此必须得归并到一个新数组。这个就是归并的过程
    整个归并排序的归并过程其实可以生动想象成:
    1. 首先tmp临时作坊得接收客户的两批原料,当然这两批原料必须得是合格的(就是说两个区间必须是各自有序的)
    2. 然后tmp临时作坊依托这两种原料在作坊里面制成了产品(把两个有序区间归并成的一个有序区间)
    3. 然后这种产品造出来后在要交付出去(也就是说给他拷贝到原先的arr数组当中)
    4. 客户不满意说我要更大的产品,就把原先产品退回来当原料造更大的(不断向上归并)
  3. 上面讲的这种归并的思想,它是建立在一个前提之上。就是首先得有两个有序的区间。比如说左区间有序加上右区间有序。那我现在没有有序呢?乱的呢?
  4. 那该怎么让左右子区间有序呢?这边采用一个分治的方法。比如说我现在想要让八个数有序,那我就先给他分成四个数,四个数,然后到时候再进行归并。然后如果说这四个数是有序的话那还好,可以直接拿来进行归并,如果说没有序的话,接下来看这个四个数的这么一个整体,我现在想让这四个数有序,那么我就给他分成两个数,两个数;然后如果说这两个数是有序的话,那么还好,就可以直接拿来进行归并,如果说这两个数是无序的话,那么就再给他分成一个数,一个数。那一个数肯定是有序的了对吧,然后一个数一个数就可以给他归并成两个;然后两个数,两个数就可以归并成四个;然后四个数,四个数就可以给他归并成八个。
    在这里插入图片描述
  5. 在归并的过程当中,必须得确保左右子区间两个都是有序的情况之下,然后才可以向上进行归并。那既然必须得确保左右两个子区间都是有序的,你必须得认识到,你肉眼看他,好像诶都已经有序了,但实际上计算机怎么知道它有序?因此你在归并递归的过程当中,必须一直深入到最后一层:也就是说每一个区间相当于只有一个数了,那这时候计算机他才知道哦这下子每一个区间都已经有序了,然后可以归并了。
    再来重复一下: 整个归并排序的归并过程其实可以生动想象成:
    1. 首先tmp临时作坊得接收客户的两批原料,当然这两批原料必须得是合格的(就是说两个区间必须是各自有序的)
    2. 然后tmp临时作坊依托这两种原料在作坊里面制成了产品(把两个有序区间归并成的一个有序区间)
    3. 然后这种产品造出来后在要交付出去(也就是说给他拷贝到原先的arr数组当中)
    4. 客户不满意说我要更大的产品,就把原先产品退回来当原料造更大的(不断向上归并)

归并排序代码实现

  1. 在归并排序当中,首先得开一个临时数组。这个临时数据的作用好比较是将原料拿过来在我数组内部做成产品然后再把整个制成品放到市场。
  2. 在归并排序的话,并不是去递归mergesort函数,而是去写一个子函数,然后去递归子函数_MergeSort
  3. 这个_MergeSort函数的功能在于把arr数组当中left-right之间区间里面的数字给他排成有序的。
  4. 首先因为我需要去平分一下左右区间,所以先要计算出mid,然后给他分成两个区间begin-mid,mid+1-end。
  5. 然后对这两个区间进行两个递归。至于到底是怎么有序的,先不用去管,反正当对这两个区间进行两次递归操作之后,这两个区间现在已经是各自有序的了。
  6. 然后就是进行归并。因为现在已经有两个有序区间了,对于这两个有序区间用begin1, end1, begin2, end2进行维护。然后归并就不讲了看代码。
  7. 当归并完了之后,现在的产品还在tmp数组里面,那么现在就要给他拷贝到原先的arr数组里面,用memcpy即可。
  8. ***归并的时候没有规定两个有序数组的数据必须个数一样,跟个数没有关系。***并没有说必须得对称。
  9. 在这里插入图片描述
  10. 再来重复一下: 整个归并排序的归并过程其实可以生动想象成:
    1. 首先tmp临时作坊得接收客户的两批原料,当然这两批原料必须得是合格的(就是说两个区间必须是各自有序的)
    2. 然后tmp临时作坊依托这两种原料在作坊里面制成了产品(把两个有序区间归并成的一个有序区间)
    3. 然后这种产品造出来后在要交付出去(也就是说给他拷贝到原先的arr数组当中)
    4. 客户不满意说我要更大的产品,就把原先产品退回来当原料造更大的(不断向上归并)
void _MergeSort(int* arr, int left, int right, int* tmp)
{
	if (left >= right)
	{
		return;
	}
	int mid = (left + right) / 2;
	_MergeSort(arr, left, mid, tmp);
	_MergeSort(arr, mid + 1, right, tmp);
	int begin1 = left;
	int end1 = mid;
	int begin2 = mid + 1;
	int end2 = right;
	int k = left;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (arr[begin1] < arr[begin2])
		{
			tmp[k++] = arr[begin1++];
		}
		else
		{
			tmp[k++] = arr[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		tmp[k++] = arr[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[k++] = arr[begin2++];
	}
	memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
}
void MergeSort(int* arr, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc failed");
		return;
	}
	_MergeSort(arr, 0, n - 1, tmp);
	free(tmp);
}

归并排序的时间复杂度

  1. 归并排序时间复杂度:对于快速排序而言的话,它实际上还要更复杂一点,因为他必须得依赖并且考虑到在单趟排序完成之后这个key的位置。因此你把地柜展开的话,它并不一定是一个满二叉树。把这边的归并排序的话,就是每一次的平分。
  2. 首先的话,它整个的高度是logN。对于分割来说,不需要消耗就直接分割O(1)。
  3. 真正的消耗在于归并。当比如说把两段有序的区间(长度为m,n)给他归并成一个区间的时候,这时候总的消耗就是O(m+n),然后你会发现每一层的归并的消耗都是n,那么整体就是NlogN。
  4. 在这里插入图片描述

在这里插入图片描述

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

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

相关文章

Android 自定义View 之 计时文字

计时文字前言正文一、XML样式二、构造方法三、API方法四、使用五、源码前言 在Android开发中&#xff0c;常常会有计时的一些操作&#xff0c;例如收验证码的时候倒计时&#xff0c;秒表的计时等等&#xff0c;于是我就有了一个写自定义View的想法&#xff0c;本文效果图。 正文…

Vue2-黑马(八)

目录&#xff1a; &#xff08;1&#xff09;router-动态路由 &#xff08;2&#xff09;router-重置路由 &#xff08;3&#xff09;router-页面刷新 &#xff08;1&#xff09;router-动态路由 我们有这样一个需求&#xff0c;不同的用户根据自己的身份不一样&#xff0c;…

Seaborn 数据可视化基础

目录 介绍 知识点 Seaborn 介绍 快速优化图形 Seaborn 绘图 API 一、散点图&#xff1a; 参数hue hue hue_order 参数style 二 、线形图 三、类别图 绘制箱线图 绘制小提琴图 绘制增强箱线图 绘制点线图 绘制条形图 绘制计数条形图 四、分布图 五、回归图 …

nginx配置

单线程应用 稳定性高 系统资源消耗低 线程切换消耗小 对HTTP并发连接处理能力高 单台服务器可支持2w个并发请求 nginx与apache区别 Nginx相对于Apache的优点: 轻量级&#xff0c;同样是 web 服务&#xff0c;比Apache 占用更少的内存及资源&#xff0c;高并发&#xff0…

攻防世界-file_include(convert.iconv的使用)

代码审计&#xff0c;存在文件包含&#xff0c;直接上伪协议 发现不行&#xff0c;应该是存在字符过滤 知识盲区&#xff1a; 1.file://协议&#xff0c;需要填写绝对路径&#xff0c;只能读取txt文件&#xff0c;后面直接跟绝对路径。 file:///etc/passwd 2.php://filter …

深入浅出 Golang 内存管理

了解内存管理~ 前言&#xff1a; 本节课主要介绍了内存管理知识与自动内存管理机制&#xff0c;并对目前 Go 内存管理过程中存在的问题提出了解决方案&#xff0c;同时结合了上次课程学习的《Go 语言性能优化》相关知识&#xff0c;提供可行性的优化建议 … 自动内存管理 Go…

spring-boot怎么扫描不在启动类所在包路径下的bean

前言&#xff1a; 项目中有多个模块&#xff0c;其中有些模块的包路径不在启动类的子路径下&#xff0c;此时我们怎么处理才能加载到这些类&#xff1b; 1 使用SpringBootApplication 中的scanBasePackages 属性; SpringBootApplication(scanBasePackages {"com.xxx.xx…

C++linux高并发服务器项目实践 day5

Clinux高并发服务器项目实践 day5程序和进程单道、多道程序设计时间片并行和并发进程控制块&#xff08;PCB&#xff09;进程状态转换进程的状态进程相关命令进程号和相关函数进程创建父子进程的关系GDB多进程调试程序和进程 程序是包含一系列信息的文件&#xff0c;这些信息描…

你知道怎么实现定时任务吗?

诸位读者都知道笔者写东西都是用到才写&#xff0c;笔者的学习足迹自从参加工作之后就是 非系统 学习了&#xff0c;公司里源代码只要有笔者不知道的技术细节&#xff0c;笔者就会仔细的研究清楚&#xff0c;笔者是不喜欢给自己留下问题的那种学习习惯。 为何要写 笔者最近负…

如何使用Thymeleaf给web项目中的网页渲染显示动态数据?

编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 操作系统&#xff1a;win10 x64 位 家庭版 服务器软件&#xff1a;apache-tomcat-8.5.27 目录一. 什么是Thymeleaf&#xff1f;二. MVC2.1 为什么需要MVC&#xff1f;2.2 MVC是什么&#xff1f;2.3 MVC和三层架构之间的关系及工…

AI绘图体验:想象力无限,创作无穷!(文生图)

基础模型&#xff1a;3D二次元 PIXEL ART &#xff08;1&#xff09;16-bit pixel art, outside of caf on rainy day, light coming from windows, cinematic still(电影剧照), hdr (2) 16-bit pixel art, island in the clouds, by studio ghibli&#xff08;吉卜力工作室…

配置基于WSL2的Docker环境并支持CUDA

导言 Content 正如前文windows 10 开启WSL2介绍的&#xff0c;我们可以在windows10中使用linux子系统。今天本文介绍如何在此基础上安装Docker并支持在wsl中使用GPU。 准备工作 加入windows insider preview。建议选Dev通道&#xff0c;不要选Beta。 安装Nvidia WSL2-compa…

【数据结构】-计数排序

&#x1f387;作者&#xff1a;小树苗渴望变成参天大树 &#x1f389; 作者宣言&#xff1a;认真写好每一篇博客 &#x1f38a;作者gitee:link 如 果 你 喜 欢 作 者 的 文 章 &#xff0c;就 给 作 者 点 点 关 注 吧&#xff01; 文章目录前言一、计数排序二、排序算法复杂度…

Nginx网站服务配置

一、Nginx概述 1.1 Nginx概述 Nginx&#xff1a; Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器&#xff0c;而且支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件…

分布式计算技术(上):经典计算框架MapReduce、Spark 解析

当一个计算任务过于复杂不能被一台服务器独立完成的时候&#xff0c;我们就需要分布式计算。分布式计算技术将一个大型任务切分为多个更小的任务&#xff0c;用多台计算机通过网络组装起来后&#xff0c;将每个小任务交给一些服务器来独立完成&#xff0c;最终完成这个复杂的计…

07 -全局状态管理

全局状态管理 7-1&#xff1a;开篇 在上一章中我们完成了 “一半” 的文章搜索功能&#xff0c;并且留下了一些问题。那么这些历史残留的问题&#xff0c;我们将会在本章节中通过 全局状态管理工具 进行处理。 那么究竟什么是 全局状态管理工具&#xff0c;如何在 uniapp 中…

【Flutter进阶】聊一聊组件中的生命周期、状态管理及局部重绘

前言 说到生命周期&#xff0c;熟悉Android开发的小伙伴一定第一时间会想到Activity的生命周期&#xff0c;由于在Flutter中一切都是组件&#xff0c;所以组件的生命周期其实是类似的。 在这个过程中组件的状态——State就非常重要&#xff0c;它记录这整个组件内可变部分的状…

【SSM整合】1—Spring和Mybatis整合

⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ Spring专栏&#x1f449;https://blog.csdn.net/weixin_53580595/category_12279588.html SpringMVC专栏&#x1f449;htt…

linux安装kafka

目录 目录 一.安装包准备&#xff1a; 二.解压安装&#xff1a; 先将该安装包放入到/opt/install目录&#xff1a; 解压该文件到soft目录中&#xff1a; 改名&#xff0c;方便后续使用&#xff1a; 三修改其中配置和配置环境变量&#xff1a; 3.1 修改/opt/soft/kafka2…

camunda工作流引擎开发架构

Camunda的开发架构可以分为前端开发架构和后端开发架构。 前端开发架构&#xff1a; Camunda前端使用Angular框架进行开发&#xff0c;主要包括以下组件&#xff1a; 1、Cockpit&#xff1a;流程监控和管理界面。 2、Tasklist&#xff1a;任务管理和审批界面。 3、Admin&…