【排序算法】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函数和前面的一样,阿辉就不水了


请添加图片描述

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

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

相关文章

LLM之llm-viz:llm-viz(3D可视化GPT风格LLM)的简介、安装和使用方法、案例应用之详细攻略

LLM之llm-viz&#xff1a;llm-viz(3D可视化GPT风格LLM)的简介、安装和使用方法、案例应用之详细攻略 目录 llm-viz的简介 1、LLM可视化 2、CPU模拟&#xff08;WIP&#xff1b;尚未公开&#xff01;&#xff09; llm-viz的安装和使用方法 llm-viz的案例应用 1、三维可视化…

智慧文旅:未来旅游业的数字化转型

随着科技的快速发展&#xff0c;数字化转型已经成为各行各业的必然趋势。旅游业作为全球经济的重要组成部分&#xff0c;也正经历着前所未有的变革。智慧文旅作为数字化转型的重要领域&#xff0c;正逐渐改变着旅游业的传统模式&#xff0c;为游客带来更加便捷、个性化的旅游体…

C语言2024-1-27练习记录

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>//int main() //{ // char c[15] { I, ,a,n,d, ,you,. }; // int i; // for(i 0; i < 15; i) //这个地方有几个地方需要注意一下&#xff0c;首先变量指定之后必须要加上英文状态下的分号 // printf("%c&q…

hash链接转磁力

有些网站下载提供的是hash链接&#xff0c;点击后跳转到专门的网站提供magnet复制&#xff0c;二维码扫描。 对比链接和磁力&#xff0c;hash部分是相同的&#xff1a; https:\\www.*********?hash********* magnet:?xturn:btih:************* 那么hash可以直接转换磁力&…

使用signal中止阻塞的socket函数的应用实例

在 socket 编程中&#xff0c;有一些函数是阻塞的&#xff0c;为了使程序高效运行&#xff0c;有一些办法可以把这些阻塞函数变成非阻塞的&#xff0c;本文介绍一种使用定时器信号中断阻塞函数的方法&#xff0c;同时介绍了一些信号处理和定时器设置的编程方法&#xff0c;本文…

nm命令如何查看目标文件符号表

概述 在Linux环境下&#xff0c;nm 是一个用来查看目标文件&#xff08;如可执行文件、动态库或静态库&#xff09;符号表的工具。使用nm命令可以很方便的查看可执行程序中有哪些函数以及动态库中有哪些导出函数。 nm命令简述 打印结果含义 先使用nm命令查看一个可执行程序…

【IM】如何保证消息可用性(一)

目录 1. 基本概念1.1 长连接 和 短连接1.2 PUSH模式和PULL模式 2. 背景介绍2.1 理解端到端的思想 3. 方案选型3.1 技术挑战3.2 技术目标 1. 基本概念 在讲解消息可用性之前&#xff0c;需要理解几个通信领域的基本概念。 1.1 长连接 和 短连接 什么是长连接&#xff0c;短连接…

MQ面试题之Kafka

前言 前文介绍了消息队列相关知识&#xff0c;并未针对某个具体的产品&#xff0c;所以略显抽象。本人毕业到现在使用的都是公司内部产品&#xff0c;对于通用产品无实际经验&#xff0c;但是各种消息中间件大差不差&#xff0c;故而本次选择一个相对较熟悉的Kafka进行详细介绍…

YoloV8改进策略:BackBone改进|DCNv4最新实践|高效涨点|多种改进教程|完整论文翻译

摘要 涨点效果:在我自己的数据集上,mAP50 由0.986涨到了0.993,mAP50-95由0.737涨到0.77,涨点明显! DCNv4是可变形卷积的第四版,速度和v3相比有了大幅度的提升,但是环境搭建有一定的难度,对新手不太友好。如果在使用过程遇到编译的问题,请严格按照我写的环境配置。 …

编程笔记 html5cssjs 061 JavaScrip简介

编程笔记 html5&css&js 061 JavaScrip简介 一、JavaScript概述二、JavaScript的主要特点三、历史延革四、JavaScript与前端开发小结 JavaScript 是 web 开发者必学的三种语言之一&#xff1a;HTML 定义网页的内容&#xff1b;CSS 规定网页的布局&#xff1b;JavaScript…

RBD —— Fracture SOP

目录 Assemble —— 清理破碎操作并生成碎片 Boolean Fracture —— 使用切割面破碎输入的几何体 Convex Decomposition —— 将输入几何体分解为凸线段 Glue Cluster —— 构建cluster值想glue约束添加强度 RBD Material Fracture —— 基于材质类型预破碎 Concrete Gl…

C++ 之LeetCode刷题记录(二十)

&#x1f604;&#x1f60a;&#x1f606;&#x1f603;&#x1f604;&#x1f60a;&#x1f606;&#x1f603; 开始cpp刷题之旅。 依旧是追求耗时0s的一天。 110. 平衡二叉树 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二…

RK3588平台开发系列讲解(视频篇)RKMedia框架

文章目录 一、 RKMedia框架介绍二、 RKMedia框架API三、 视频处理流程四、venc 测试案例沉淀、分享、成长,让自己和他人都能有所收获!😄 📢RKMedia是RK提供的一种多媒体处理方案,可实现音视频捕获、音视频输出、音视频编解码等功能。 一、 RKMedia框架介绍 功能: VI(输…

【Redis笔记】缓存——缓存分类、缓存穿透、缓存雪崩、缓存击穿

缓存 缓存(Cache),就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于高速存储媒介上。 缓存的本质就是用空间换时间&#xff0c;牺牲数据的实时性&#xff0c;以服务器内存中的数据暂时代替从数据库读取最新的数据&#xff0c;减少数据库IO&#…

2401llvm,匹配器参考

返回类型名字参数Matcher<attr>attrMatcher<Attr>... 匹配属性. 属性可附加各种不同的语法(包括关键字,C11属性,GNU的__attribute和MSVC的__declspec,和#pragma等).也可能是隐含的. 给定 struct [[nodiscard]] Foo{};void bar(int * __attribute__((nonnull)) );…

一起学习ETCD系列——运维操作之etcdctl使用

文章目录 概要一、命令二、实操2.1、基本操作2.2、watch2.3、租约2.4、分布式锁2.5、角色2.6、用户2.7、认证2.8、集群 概要 本文主要用来总结ETCD客户端ctcdctl的命令操作&#xff0c;在运维过程中可能常常用到的。 一、命令 etcd工具 etcdctl官方命令示例 [roottest etcd…

【牛客刷题】笔试选择题整理(day1-day2)

每天都在进步呀 文章目录 1. 小数求模运算2. 进程的分区&#xff0c;这里说的不是JVM的分区。进程中&#xff0c;方法存放在方法区。3. 访问权限控制4. 继承与多态5. 与equals()6. 类加载顺序7. super()与this()7.1 super7.1.1 super调用父类构造方法7.1.2 super调用父类属性和…

私人漫画图书馆:分类管理,一目了然 | 开源日报 No.157

tachiyomiorg/tachiyomi Stars: 26.9k License: Apache-2.0 tachiyomi 是一个免费开源的安卓漫画阅读器。 该项目的主要功能、关键特性、核心优势包括&#xff1a; 从多种来源在线阅读本地阅读已下载内容可配置的阅读器&#xff0c;具有多个查看器、翻页方向和其他设置支持追…

大数据处理系统的架构

大数据处理系统的架构介绍 Lamdba架构 Lambda 架构是一种用于处理大规模数据的设计模式,旨在结合批处理和实时处理,以应对对大量数据进行高效处理的需求。Lambda 架构的核心思想是将数据处理流程分为批处理层和实时处理层,并将它们整合在一起,以获得高可扩展性和灵活性。…

什么叫高斯分布?

高斯分布&#xff0c;也称为正态分布&#xff0c;是统计学中最常见的概率分布之一。它具有钟形曲线的形态&#xff0c;对称分布在均值周围&#xff0c;且由均值和标准差两个参数完全描述。 高斯分布的概率密度函数&#xff08;Probability Density Function, PDF&#xff09;可…