归并排序-排序算法

前言

如果一个数组的左右区间都有序,我们可以使用一种方法(归并),使这个数组变得有序。

如下图:

过程也很简单,分别取左右区间中的最小元素,再把其中较小的元素放到临时数组中,例如第一次1和2被取出,1 被放到临时数组;第二次3和2被取出,2 被放到临时数组。重复此操作就能得到有序的临时数组,最后把临时数组拷贝到原数组中就好了。

这就是归并的思想,目前先依照上面过程写出归并方法的代码。注意不是归并排序的代码

#include <iostream>
using namespace std;

void mergeAdd0(int arr[], int left, int right,int *temp) //函数参数传入临时数组
{
	int mid = (left + right) / 2 ; //区间的中间位置,[left,mid]为左区间,[mid+1,right]为右区间
	int i = left;		//指向左区间最小元素的位置
	int j = mid + 1 ;	//指向右区间最小元素的位置
	int k = 0;			//临时数组的下标

	while (i <= mid && j <= right) //这个循环是取出元素的过程
	{
		if (arr[i] < arr[j])
		{
			temp[k++] = arr[i++];
		}
		else
		{
			temp[k++] = arr[j++];
		}
	}
    
    //因为有一个区间的元素必定会先被取完,下面两个循环是将另一个区间的元素拿到临时数组
	while (i <= mid)
	{
		temp[k++] = arr[i++];
	}

	while (j <= right)
	{
		temp[k++] = arr[j++];
	}

	//将temp数组拷贝到原数组
	memcpy(arr + left, temp, sizeof(int) * (right - left + 1 ));

}
int main(void)
{
	int arr[] = { 1 , 3, 5 ,7 ,2 ,4 ,6 ,8 };
	int len = sizeof(arr) / sizeof(arr[0]);

	int* temp = new int[len]; //和原数组大小一样的临时数组
	mergeAdd0(arr, 0, len - 1,temp);

	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";
	}
	return 0;
}

看完了归并方法,有些人会问,你这个归并方法并不能适用于一般情况,一般数组都是无序的,哪里是你那样的数组:左半边有序,右半边也有序。

也是,下面请先看看归并排序的过程吧(也就是处理一般情况)。

具体步骤

接下来讲的就是排序本身的具体步骤了,对于下面待排序的数组

——170 189 187 186 169 173 162 170 168——

先以中间为界,均分为A、B两组(如果是奇数个,允许两组的个数相差一个)

A——170 189 187 186 169——

B——173 162 170 168——

如果A、B两组数据有序的话,那么就可以通过上面的归并方法让数组有序,可是此时两个数组都无序,此时可以使用分治法继续对A、B两组进行均分,以B组为例,可以分为B1、B2组如下:

B1——173 162——

B2——170 168——

均分后依旧无序,继续利用分治法细分,以B1组为例,可分为如下两组

B11——173——

B12——162——

数组细分到一个元素后,这时候就可以使用之前的归并法借助一个临时数组将B1组有序化!B2数组同理。

B1——162 173——

B2——168 170——

依次类推,B1、B2组有序后,可归并成有序的B组,A组同理。

A——169 170 186 187 189——

B——162 168 170 173——

最后将A、B两组通过归并法合并得到了有序的数组。

——162 168 169 170 170 173 186 187 189——

思路

上面这个过程,按我的理解是:首先归并方法可以使一个左区间有序、右区间有序的数组有序,那左区间怎么有序呢?

恭喜你,学会抢答了。那就是左区间的左区间有序并且左区间的右区间有序(使用归并方法),右区间同理。那左区间的左区间如何有序呢?……直到细分到区间内只有一个元素时,可以保证这个区间有序,从而得到一个个有序区间,最终使数组有序。

这个过程正如排序的名称归并,先递归,使大问题变成小问题,再合并,依次解决问题。

就如上过程结合归并方法可以得到以下代码:

//归并排序
void mergeSort(int arr[], int left, int right, int* temp)
{
	if (left < right) //区间大于1个数,就要分而治之
	{
		int mid = (left + right) / 2;
		mergeSort(arr, left, mid, temp);  
		mergeSort(arr, mid+1, right, temp);  
		mergeAdd(arr, left, right, temp); 
	}
}

归并排序时间复杂度:nlog_{2}^{n} 

全部代码以及测试图

#include <iostream>
#include <time.h>
using namespace std;

//归并方法
void mergeAdd(int arr[], int left, int right,int *temp)
{
	int mid = (left + right) / 2 ; //区间的中间位置,[left,mid]为左区间,[mid+1,right]为右区间
	int i = left;		//指向左区间最小元素的位置
	int j = mid + 1 ;	//指向右区间最小元素的位置
	int k = 0;			//临时数组的下标

	while (i <= mid && j <= right)
	{
		if (arr[i] < arr[j])
		{
			temp[k++] = arr[i++];
		}
		else
		{
			temp[k++] = arr[j++];
		}
	}

	while (i <= mid)
	{
		temp[k++] = arr[i++];
	}

	while (j <= right)
	{
		temp[k++] = arr[j++];
	}

	//将temp数组拷贝到原数组
	memcpy(arr + left, temp, sizeof(int) * (right - left + 1 ));

}

//归并排序
void mergeSort(int arr[], int left, int right, int* temp)
{
	if (left < right) //区间大于1个数,就要分而治之
	{
		int mid = (left + right) / 2;
		mergeSort(arr, left, mid, temp);  
		mergeSort(arr, mid+1, right, temp);  
		mergeAdd(arr, left, right, temp); 
	}
}
int main(void)
{
	int arr[] = { 170 ,189,187 ,186 ,169 ,173 ,162 ,170 ,168 };
	int len = sizeof(arr) / sizeof(arr[0]);

	int* temp = new int[len]; //和原数组大小一样的临时数组
	
	mergeSort(arr, 0, len - 1, temp);
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";
	}
	
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaSE学习笔记 2023-12-28 --MySQL

MySQL 个人整理非商业用途&#xff0c;欢迎探讨与指正&#xff01;&#xff01; 文章目录 MySQL1.数据库介绍2.数据库的分类3.数据库中的常用术语4.数据库安装和配置5.MySQL的逻辑结构6.SQL语句7.DML7.1DQL7.1.1基本查询7.1.2过滤查询7.1.2.1条件运算符7.1.2.2逻辑运算符7.1.2.…

Spring 基于注解的AOP见解4

5.基于注解的AOP配置 5.1创建工程 5.1.1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&…

【AI视野·今日NLP 自然语言处理论文速览 第六十七期】Mon, 1 Jan 2024

AI视野今日CS.NLP 自然语言处理论文速览 Mon, 1 Jan 2024 Totally 42 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Principled Gradient-based Markov Chain Monte Carlo for Text Generation Authors Li Du, Afra Amini, Lucas…

基于Springboot的计算机学院校友网(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的计算机学院校友网(有报告)。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring…

红队打靶练习:RICKDICULOUSLYEASY: 1

目录 信息收集 1、arp 2、nmap 3、nikto 4、whatweb 目录探测 gobuster dirsearch WEB get flag1 /robots.txt FTP get flag2 telenet登录 get flag3 get flag4 9090端口 get flag5 dirsearch ssh登录 Summer用户 get flag6 信息收集 get flag7 get fl…

目标检测数据集大全「包含VOC+COCO+YOLO三种格式+划分脚本+训练脚本」(持续原地更新)

一、作者介绍&#xff1a;五年算法开发经验、AI 算法经理、阿里云开发社区专家博主、稀土掘金人工智能内容评审委员会成员。擅长&#xff1a;检测、分割、理解、AIGC 等算法训练与部署。 二、数据集介绍&#xff1a; 质量高&#xff1a;高质量图片、高质量标注数据&#xff0c;…

Java中什么序列化?

在Java中&#xff0c;序列化是一种将对象转换为字节序列的机制&#xff0c;使得对象可以在网络上传输或存储到文件中&#xff0c;而后可以通过反序列化还原为对象。Java提供了java.io.Serializable接口&#xff0c;通过实现这个接口的类可以实现对象的序列化和反序列化。 序列…

众和策略:沪指跌0.91%险守2900点,半导体、金融等板块走低

8日早盘&#xff0c;两市股指低开低走&#xff0c;沪指一度失守2900点&#xff0c;深成指、创业板指跌约1%&#xff0c;科创50指数创前史新低。 到午间收盘&#xff0c;沪指跌0.91%报2902.4点&#xff0c;深成指跌1.17%&#xff0c;创业板指跌0.99%&#xff0c;科创50指数跌超…

唠一唠Java线程池

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;咱们今天来聊聊Java线程池&#xff0c;如果没有线程池&#xff0c;每个线程都需要手动创建和销毁线程&#xff0c;那将是多么低效和耗资源啊&#xff01; 线程池的核心作用就是复用已创建的线程&#xff0c;减少…

使用电脑多年的你不可不知:移动机械硬盘的正确使用姿势

前言 随着科技的发展&#xff0c;小伙伴手边或多或少都有移动硬盘这个存储设备。上班族用来存储资料&#xff0c;家人用来存放回忆。但移动机械硬盘的使用过程中是有注意事项的&#xff0c;你知道多少移动机械硬盘的使用注意事项呢&#xff1f; 今天小白就跟各位小伙伴来唠唠…

好用的设备租赁管理软件有哪些?

“我们公司是做设备租赁的&#xff0c;想找一款适合设备租赁的库存管理软件&#xff0c;最好有库存管理&#xff0c;客户信息&#xff0c;设备外调管理&#xff0c;租赁天数管理&#xff0c;设备的借出与归还信息管理与查询。” 总结一下—— 库存管理客户信息管理设备租赁管…

softmax详解

在神经网络中&#xff0c;Softmax 是一个用于多类别分类的激活函数。给定一个包含原始分数&#xff08;未经处理的模型输出&#xff09;的向量&#xff0c;Softmax 将这些分数转化为表示概率分布的向量。具体而言&#xff0c;对于给定的原始分数向量 ( z )&#xff0c;Softmax …

Transformers 2023年度回顾 :从BERT到GPT4

人工智能已成为近年来最受关注的话题之一&#xff0c;由于神经网络的发展&#xff0c;曾经被认为纯粹是科幻小说中的服务现在正在成为现实。从对话代理到媒体内容生成&#xff0c;人工智能正在改变我们与技术互动的方式。特别是机器学习 (ML) 模型在自然语言处理 (NLP) 领域取得…

《网络是怎样连接的》2.5节图表(自用)

图5.1&#xff1a;ip包结构 图5.2&#xff1a;ip网络包的传输方式 1.以太网的部分也可以替换成其他的东西&#xff0c;例如无线局域网、ADSL、FTTH等&#xff0c;它们都可以替代以太网的角色帮助IP协议来传输网络包 2.根据ARP协议&#xff0c;客户端可以根据ip地址得到下一个路…

vsCode输出控制台中文乱码解决

在tasks.json里的args中添加 "-fexec-charsetGBK", // 处理mingw中文编码问题 "-finput-charsetUTF-8",// 处理mingw中文编码问题

VMware Workstation安装以及配置模板机

文章目录 一、VMware Workstation软件下载安装1、下载2、安装 二、CentOS7模板机安装1、创建虚拟机2、安装系统 三、网络配置 一、VMware Workstation软件下载安装 1、下载 下载地址&#xff1a;https://download3.vmware.com/software/wkst/file/VMware-workstation-full-15…

[Vulnhub靶机] DriftingBlues: 5

[Vulnhub靶机] DriftingBlues: 5靶机渗透思路及方法&#xff08;个人分享&#xff09; 靶机下载地址&#xff1a; https://download.vulnhub.com/driftingblues/driftingblues5_vh.ova 靶机地址&#xff1a;192.168.67.24 攻击机地址&#xff1a;192.168.67.3 一、信息收集 …

C#高级语法 Attribute特性详解和类型,方法,变量附加特性讲解

文章目录 前言相关资料Attribute特性个人原理理解特性的声明与使用类型特性运行结果&#xff1a; 找到类的Attribute属性方法特性和变量特性代码封装测试类TestService1TestService2TestService3 测试代码运行结果 对封装的代码进行优化封装代码测试代码运行结果&#xff08;和…

C#,入门教程(13)——字符(char)及字符串(string)的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(12)——数组及数组使用的基础知识https://blog.csdn.net/beijinghorn/article/details/123918227 字符串的使用与操作是必需掌握得滚瓜烂熟的编程技能之一&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; C#语言实…

POSIX API与网络协议栈

本文介绍linux中与tcp网络通信相关的POSIX API&#xff0c;在每次调用的时候&#xff0c;网络协议栈会进行的操作与记录。 POSIX API Posix API&#xff0c;提供了统一的接口&#xff0c;使程序能得以在不同的系统上运行。简单来说不同的操作系统进行同一个活动&#xff0c;比…