归并排序-排序算法

news2024/11/14 16:46:09

前言

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

如下图:

过程也很简单,分别取左右区间中的最小元素,再把其中较小的元素放到临时数组中,例如第一次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;
}

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

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

相关文章

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

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

近似点梯度法

最优化笔记——Proximal Gradient Method 最优化笔记&#xff0c;主要参考资料为《最优化&#xff1a;建模、算法与理论》 文章目录 最优化笔记——Proximal Gradient Method一、邻近算子&#xff08;1&#xff09;定义 二、近似点梯度法&#xff08;1&#xff09;迭代格式&…

【JAVA】怎么确保一个集合不能被修改

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 示例&#xff1a; 不可修改的List&#xff1a; 不可修改的Set&#xff1a; 不可修改的Map&#xff1a; 结语 我的其他博…

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

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

【数据库】mysql事务

一、事务的基本概念 1、事务的定义 事务可由一条非常简单的SQL语句组成&#xff0c;也可以由一组复杂的SQL语句组成。。 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。事务处理可以用来维护数据库的完整性&#xff0c;保证成批的 SQL 语句要么全部执行&…

Java项目:112SSM在线电影订票系统

博主主页&#xff1a;Java旅途 简介&#xff1a;分享计算机知识、学习路线、系统源码及教程 文末获取源码 一、项目介绍 在线电影订票系统基于SpringSpringMVCMybatis开发&#xff0c;系统分为前台和后台&#xff0c;前台主要用来用户浏览电影信息&#xff0c;订票&#xff0c…

第7章-第9节-Java中的Stream流(链式调用)

1、什么是Stream流 Lambda表达式&#xff0c;基于Lambda所带来的函数式编程&#xff0c;又引入了一个全新的Stream概念&#xff0c;用于解决集合类库既有的鼻端。 2、案例 假设现在有一个需求&#xff0c; 将list集合中姓张的元素过滤到一个新的集合中&#xff1b;然后将过滤…

Dell 机架式服务器 - 高级定制服务

Dell 机架式服务器 - 高级定制服务 1. Dell Technologies2. 机架式服务器 - 高级定制服务2.1. Servers & Storage (服务器及存储) -> Servers2.2. Rack Servers (机架式服务器)2.3. Shop2.4. PowerEdge Rack Servers (PowerEdge 机架式服务器)2.5. PowerEdge R760 Rack …

个性化Python GUI计算器搭建

大家好&#xff0c;本文将介绍在Python中使用Tkinter几分钟内制作自己的全功能GUI计算器。 要完成所提到的功能&#xff0c;除了通常随Python标准库一起安装的Tkinter之外&#xff0c;不需要任何额外的库。 如果使用的是Linux系统&#xff0c;可能需要安装&#xff1a; $ pi…

519基于单片机的自动切割流程控制系统

基于单片机的自动切割流程控制系统[proteus仿真] 自动切割流程控制系统这个题目算是课程设计和毕业设计中常见的题目了&#xff0c;本期是一个基于单片机的自动切割流程控制系统 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】&#xff0c;赞赏任意文章 2&…

双指针(简化哈希)力扣15.三数之和

题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 …

密码学(二)

文章目录 前言一、Certificate Authorities二、Key Agreement Protocols 前言 本文来自 Intel SGX Explained 请参考&#xff1a;密码学&#xff08;一&#xff09; 一、Certificate Authorities 非对称密钥密码学中的公钥和私钥假设每个参与方都拥有其他参与方的正确公钥。…

【上海】买套二手房需要多少钱?

上次我们看了苏州的二手房&#xff0c;这次我们一起来看下上海的二手房价格如何。 数据来源 数据来自贝壳二手房&#xff0c;每个区最多获取了3千条房源信息&#xff0c;数据共计4万条左右 对数据感兴趣的朋友&#xff0c;公众号后台发送上海二手房获取数据文件 各区房源单价…

【VRTK】【VR开发】【Unity】19-VRTK实现旋转运动

课程配套学习项目源码资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【背景】 在实际开发中,旋转运动也是时常需要模拟的重要运动类型。常见的场景有开关门,方向盘轮胎以及拉动拉杆等等。 旋转运动的实现可以基于物理系…

STM32入门教程-2023版【3-3】gpio输入

关注 星标公众号 不错过精彩内容 大家好&#xff0c;我是硬核王同学&#xff0c;最近在做免费的嵌入式知识分享&#xff0c;帮助对嵌入式感兴趣的同学学习嵌入式、做项目、找工作! 上两小节我们已经把GPIO的结构和8种输入输出模式都讲完了&#xff0c;到这里还不懂的可以回…

JVM主要的几种垃圾回收算法

1、Java 为什么要实现自动内存管理 &#xff1f; 简化开发过程&#xff1a;通过内存自动管理可以避免手动分配和释放内存的麻烦&#xff0c;减少了内存泄漏和内存错误的风险&#xff0c;让研发能更专注于业务逻辑&#xff0c;不必纠结于内存管理的细节。 提高开发效率&#xff…

vivado 创建编译后工程

创建后期合成项目 合成后项目以合成网表、完全生成的块设计、完全生成的IP以及相应的约束。然后&#xff0c;您可以分析、布局和实施设计 注意&#xff1a;您可以使用XST或第三方合成工具来创建合成网表。 重要&#xff01;使用EDIF和NGC文件时&#xff0c;顶部单元格名称必…

ChatGPT扩展系列之网易数帆ChatBI

在当今数字化快速发展的时代,数据已经成为业务经营与管理决策的核心驱要素。无论是跨国大企业还是新兴创业公司,正确、迅速地洞察数据已经变得至关重要。然而,传统的BI工具往往对用户有一定的技术门槛,需要熟练的操作技能和复杂的查询语句,这使得大部分的企业员工难以深入…

业界首款PCIe 4.0/5.0多通道融合接口SSD技术解读

之前小编写过一篇文章劝大家不要碰PCIe 5.0 SSD&#xff0c;详细内容&#xff0c;可以再回顾下&#xff1a; 扩展阅读&#xff1a;当下最好不要入坑PCIe 5.0 SSD 如果想要进一步了解PCIe 6.0&#xff0c;欢迎点击阅读&#xff1a; 浅析PCIe 6.0功能更新与实现的挑战 PCIe 6.…

Hyperledger Fabric 消息协议

Fabric 中大量采用了 gRPC 消息在不同组件之间进行通信交互&#xff0c;主要包括如下几种情况&#xff1a;客户端访问 Peer 节点&#xff0c;客户端和 Peer 节点访问排序节点&#xff0c;链码容器与 Peer 节点交互&#xff0c;以及多个 Peer 节点之间的 Gossip 交互。 消息结构…