【排序算法】C语言实现归并排序,包括递归和迭代两个版本

请添加图片描述

文章目录

  • 🚀前言
  • 🚀归并排序介绍及其思想
  • 🚀递归实现
  • 🚀迭代实现

🚀前言

大家好啊!阿辉接着更新排序算法,今天要讲的是归并排序,这里阿辉将讲到归并排序的递归实现迭代实现,话不多说,开始咱们今天的学习吧!!!!

🚀归并排序介绍及其思想

归并排序这是阿辉讲的第一个时间复杂度O(nlogn)的排序算法,额外空间复杂度是O(n),归并排序可以做到稳定性。

思想
归并排序的思想就是分治分治的思想是将一个大问题分解成若干个小问题,然后分别解决这些小问题,最后将这些小问题的解合并起来得到原问题的解

由分治的思想很容易,想到用递归来实现归并排序,我们接着看👇

🚀递归实现

关于归并排序的递归方法主要由三个大的逻辑组成:

  • 分解:将待排序的数组分成两个子数组
  • 解决:对每个子数组进行排序
  • 合并:将排序好的子数组合并成一个有序的数组

这里我们使用递归很轻松就能把主逻辑写好,大家都知道写递归必须要有限制条件否则会造成死递归,对于归并排序的限制条件很简单,对于数组只有一个元素时自然就是有序的,直接返回即可

主逻辑:
merge函数相当于黑盒,作用就是把两个有序数组合成一个大的有序数组

void MergeSort(int a[], int l, int r) {// C/C++归并排序递归版本,主逻辑
	if (r == l) {//递归限制条件
		return;
	}
	int m = l + ((r - l) >> 1);//数组中位置下标
	MergeSort(a, l, m);//左部分排序
	MergeSort(a, m + 1, r);//右部分排序
	merge(a, l, m, r);//两部分有序数组合并
}

整个归并排序最重要的部分也就是有序数组合并的部分:
请添加图片描述

merge函数实现,还是不太懂的可以看一下下面的代码,有详细的注释
C语言版本:

void merge(int a[], int l, int m, int r) {
	int* help = (int*)malloc((r - l + 1) * 4);//申请辅助空间
	int i = 0;//作为help指针的偏移量,存储两有序数组排好序的大数组
	int first = l;//作为左部分数组的起始下标
	int second = m + 1;//作为右部分数组的起始下标
	while (first <= m && second <= r) {//哪一方下标越界就说明不用继续比较了
		//三目运算代码更简洁,谁小谁在前先赋值给help,后置++,
		// 赋值后i向后偏移一个位置,second或first也向后偏移一个位置
		help[i++] = a[first] <= a[second] ? a[first++] : a[second++];
	}
	//下面虽然两个while循环但是只会进去一个
	//还没存进help数组的继续存
	while (first <= m) {
		help[i++] = a[first++];
	}
	while (second <= r) {
		help[i++] = a[second++];
	}
	//最后把help管理的值,还原到原数组a中
	for (i = 0; i < r - l + 1; i++) {
		a[l + i] = help[i];
	}
	free(help);//释放申请的堆空间
	help = NULL;//野指针系上绳子
}

C++版本:
也就是用了STL的容器更方便

 void merge(vector<int>& arr, int l, int mid, int r) {//合并有序数组
	vector<int> help(r - l + 1, 0);//用一个额外的数组装排好的数
	int first = l;
	int second = mid + 1;
	int i = 0;
	//合并过程
	while (first <= mid && second <= r) {
		help[i++] = arr[first] <= arr[second] ? arr[first++] : arr[second++];
	}
	while (first <= mid) {
		help[i++] = arr[first++];
	}
	while (second <= r) {
		help[i++] = arr[second++];
	}
	//将help数组拷贝到原数组
	for (int i = 0; i < r - l + 1; i++) {
		arr[l + i] = help[i];
	}
}

🚀迭代实现

归并排序的迭代实现就是把主逻辑从递归改为迭代了,有序合并部分并没有改变还是上面实现的merge函数
其实就是从递归的条件返回那一步往后推:
这里我们引入一个概念步长,用来表示左部分和右部分的数组长度,步长从1开始,然后每次倍增,就相当于递归的回溯过程
上图:
步长为左右部分长度,左右部分进行merge操作,没有右部分的跳过
请添加图片描述
主逻辑:

void MergeSort(int a[], int l, int r) {
	int len = 1;//步长
	while (len <= r) {
		l = 0;
		while (l <= r) {
			int m = l + len - 1;//计算左部分的最后一个位置
			if (m >= r) {//此时说明没有右部分,可以跳出循环进行下一轮了
				break;
			}
			//m + len是右部分的最后一个位置与r做比较防止越界,拿到一个正确的merge右边界
			int n = r <= m + len ? r : m + len;
			merge(a, l, m, n);
			l = n + 1;
		}
		if (len > r / 2) {//假如数组很长len×2可能溢出,防止溢出变成负数死循环
			break;
		}
	}
}

merge函数和前面的一样,阿辉就不水了


请添加图片描述

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

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

相关文章

CPU中的算术逻辑单元(ALU)

ALU有2个单元&#xff0c;1个算术单元和1个逻辑单元 算数单元 1 bit加法 半加器 由一个异或门&#xff08;XOR&#xff09;和与门&#xff08;AND&#xff09;两个逻辑门构成&#xff0c;异或门表示无进位加法&#xff08;sum&#xff09;&#xff0c;而与门表示进位&…

k-Wave仿真例程:创建超声换能器并绘制声场分布

k-Wave介绍 k-Wave软件是为了模拟超声波在1D、2D或3D中的传播。 应用示例包括&#xff1a; - 均匀和非均匀介质中的传播 - 模拟各种类型的传感器 - 模拟多普勒效应 - 衍射、折射和反射 - 光声、超声成像 - 波束合成、成像重建 - 模拟弹性波 安装k-Wave 安装k-Wave需要几个步…

基于springboot+vue的小徐影城管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

移动端测试如何学,超详细的APP测试攻略送上

前言 随着手机应用市场发展的逐渐成熟&#xff0c;手机APP已经渗透到人们的吃穿住行生活&#xff0c;比如手机支付APP、通讯APP、各大应用软件等&#xff0c;关于手机APP安全性能的重要性不言而喻。 鉴于此&#xff0c;做好手机APP测试对于软件开发方把控产品质量有着重要意义…

计算机408真的很难吗❓|深度分析+实操上岸规划

在下面这篇文章中&#xff0c;LUCEN详细分析了24考研的难度以及25考研人该怎么办 24考研计算机很难&#xff01;25考研你就这么干 如果你对于计算机考研择校有任何疑问&#xff0c;那么下面这篇文章一定能够帮助你&#xff1a; 计算机择校指南&#xff0c;内含300所院校 如…

Linux命令-top

1、top命令简介 top命令是linux系统常用命令之一&#xff0c;能够实时显示系统各个进程的资源占用情况&#xff0c;类似于windows系统的任务管理器。 需要注意的是&#xff1a;top命令监控的最小单位是进程&#xff0c;如果想监控更小单位时&#xff0c;就需要用到ps或者nets…

代码评审——随机数Random问题

问题描述&#xff1a; 为了获取唯一值&#xff0c;经常会依赖产生随机数来保证唯一性。在获取随机数时&#xff0c;如果使用错误的方法&#xff0c;会比较低效。 可以参考以下代码&#xff1a; public static String geneRundomNo(){Random rnew Random();int numr.nextInt(…

springboot114基于多维分类的知识管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的基于多维分类的知识管理系统 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章…

Server-Sent Events(SSE)简单实现实时通信

Server-Sent Events&#xff08;SSE&#xff09;是一种基于HTTP的实时通信协议&#xff0c;它允许服务器向客户端推送信息。相比于传统的轮询方式&#xff0c;SSE 提供了更加轻量级和实时的通信机制。在本文中&#xff0c;我们将深入浅出地介绍如何简单实现 Server-Sent Events…

在上海做程序员这么多年,退休后我的工资是多少?

大家好&#xff0c;我是拭心。 最近看到一个很可惜的事&#xff1a;有个阿姨在深圳缴纳了 12 年社保&#xff0c;第 13 年家里突然有事不得不回老家&#xff0c;回去后没再缴纳社保&#xff0c;结果退休后无法领退休工资&#xff0c;还得出来打工赚钱。 之所以这样&#xff0…

STL常用容器—stack与queue容器(栈与队列)

STL常用容器—stack与queue容器&#xff08;栈与队列&#xff09; stack容器1. stack容器模型图2. stack 基本概念3. stack 常用接口 queue 容器1. queue 容器模型图2. queue 基本概念3. queue 常用接口 参考博文1&#xff1a;&#xff1c;C&#xff1e; stack与queue容器概念模…

这种环境下腾讯64亿在北京拿地?

近期&#xff0c;金融市场出现较大波动&#xff0c;A股指数跌至2700点&#xff0c;同时恒生指数也下滑至15000点&#xff0c;引发了社会各界的关注和思考。与此同时&#xff0c;腾讯以64.2亿元拿下北京海淀区地块&#xff0c;马云和蔡崇信又增持阿里股票&#xff0c;这一系列的…

【Java网络编程01】网络原理初识

【Java网络编程01】网络原理初识 1. 网络通信基础概念 网络通信&#xff1a;网络互连的目的就是网络通信&#xff0c;即网络数据传输&#xff0c;再直白点而言就是不同主机的不同进程之间基于网络进行数据的传输交互。 那么&#xff0c;在组建的网络上有各种各样的主机&#…

【Conda】超详细的linux-conda环境安装教程

背景 最近被python各个版本环境整的头晕目眩&#xff0c;本来就不是专长做python的&#xff0c;切换各种版本着实不好操作&#xff0c;因此想到了conda这个好工具&#xff0c;以下是对conda的相关理解和搭建的详细过程&#xff0c;做个记录。 Conda简介 Conda是在Windows、m…

3.Eureka注册中心

3.Eureka注册中心 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图&#xff1a; 大家思考几个问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址和端口&#xff1f;有多个user-service实例地址&#xff0…

Redis - redis.windows.conf配置文件及RDB和AOF数据持久化方案

Redis - redis.windows.conf配置文件及RDB和AOF数据持久化方案 Redis的高性能是由于其将所有数据都存储在了内存中&#xff0c;为了使Redis在重启之后仍能保证数据不丢失&#xff0c;需要将数据从内存中同步到硬盘中&#xff0c;这一过程就是持久化。 Redis支持两种方式的持久化…

Vue 的 事件修饰符and按键修饰符

1、事件修饰符概览 修饰符说明 .prevent阻止默认事件 .stop阻止冒泡.once事件只触发一次 .capture 添加事件侦听器时使用事件捕获模式.self只有点击当前元素本身时才会触发回调.passive事件的默认行为立即执行&#xff0c;无需等待事件回调执行完毕(不常用).native 将vue组件…

【单例模式】保证线程安全实现单例模式

&#x1f4c4;前言&#xff1a;本文是对经典设计模式之一——单例模式的介绍并讨论单例模式的具体实现方法。 文章目录 一. 什么是单例模式二. 实现单例模式1. 饿汉式2. 懒汉式2.1 懒汉式实现单例模式的优化&#xff08;一&#xff09;2.2 懒汉式实现单例模式的优化&#xff08…

蓝桥杯官网填空题(01串的熵)

问题描述 答案提交 这是一道结果填空的题, 你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。 import java.util.*;public class Main {public static void main(String[] args) {for(double zero1;zero<2333…