当前位置: 首页 > news >正文

算法之归并排序

文章目录

  • 一、归并排序(递归版)
  • 二、归并排序(非递归版)


一、归并排序(递归版)

归并排序思想:将数组划分为两个区间,左区间,右区间 然后对这两个区间内容进行排序 ,这两个区间排好序之后再将其合并为一个有序的区间
在这里插入图片描述

这两个区间排好序之后,再将这两个区间合并为一个区间 也就是将这两个区间的数据排序为一个有序的区间
而将数组划分为两个区间之后是如何将这两个区间里的内容排好序的呢 是重复同样的操 作再将这两个区间中的左区间分别又划分为两个区间(左区间,右区间)在这里插入图片描述
,将这两个区间分别排好序之后,
再归为一个区间,也就是左区间有序了,然后再排它的右区间,此时它的右区间右划分为两个区间(左区间,右区间)在这里插入图片描述
对它们分别进行排序 ,而划分下去的左右区间又要执行同样的操作,直到最后区间大小为一时,那么此时就不用排返回,返回时与另一个区间比较进行排序,
最后右区间变为有序的了,最后将这两个大的左右区间归并排序为一个区间,此时这个区间有序 ,由于递归排序回来时,将小区间排好序,最后整个大区间跟着有序了在这里插入图片描述
我上图只是画了整个数组左区间的,右区间可以下去尝试下,右区间也是如此

void _MergeSort(int* a, int left, int right, int* tmp)
{//当区间中只有一个数时就不用再对其进行排序if (left >= right)return;//每次将其区间折半划分为左区间和右区间int mid = (left + right) / 2;//再重复划分,直到它的左右区间只剩下一个数,那么再返回//对其排序_MergeSort(a, left, mid, tmp);_MergeSort(a, mid + 1, right, tmp);//将其小区间排好序后再排它的大区间//小区间有序之后大区间排过来也就是有序的了int begin1 = left, end1 = mid;int begin2 = mid + 1, end2 = right;int begin = left;//将左右区间合并为一个区间while (begin1 <= end1 && begin2 <= end2){if (a[begin1] > a[begin2]){tmp[begin++] = a[begin2++];}else{tmp[begin++] = a[begin1++];}}//两个区间中还剩余数据的那个区间直接尾插到tmp数组后面while (begin1 <= end1){tmp[begin++] = a[begin1++];}while (begin2 <= end2){tmp[begin++] = a[begin2++];}//最后将排好序的区间拷贝回原来的数组memcpy(a + left, tmp+left, sizeof(int)*(right - left + 1));
}void MergeSort(int* a, int n)
{//开一个临时数组用来存放小区间排序后的数据//最后再将排序后的数组拷贝回原数组中int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail\n");return;}//归并排序分两区间进行_MergeSort(a, 0, n - 1, tmp);free(tmp);
}

二、归并排序(非递归版)

思想:将整个数组一个数与一个数比较,然后将它们排序为一个有两个数的区间 得到两个数与两个数之间有序
再将有两个数的区间与另外有两个数的区间进行排序为一个有四个数的区间 得到四个数的区间与四个数的区间有序
再将四个数的有序区间与四个数的有序区间进行排序为一个有8个数的有序区间 得到8个数与8个数之间有序
如此循环下去,直到区间中数据的个数为原数组数据个数时为止
那么区间中的数据个数如何控制,它又是如何变化的,设定一个变量gap来控制,然后当数组里面的数据都两两归并后gap变为原来2倍
gap *= 2
在这里插入图片描述

当数组长度不是gap倍数时,要注意控制边界。

那这个边界如何控制?

设前一个区间左端:begin1,右端:end1
设后一个区间左端为:begin2,右端:end2
如果第一个区间的右端已经超出了数组长度(end1>=n),此时将第一个区间右端下标重定为数组长度-1(end1 =n-1, begin2 = n, end2 = n-1),如果前一个区间右端没有超出,但是第二个区间左端就超出了(重定begin2 = n-1,end2 = n-1,),这样后一个区间就不用再与前一个区间合并了,直接将前一个区间拷到原数组后面,如果后一个区间左端没有超出,但是后一个区间右端超出了数组长度,此时重定end2,end2 = n-1,此时前一个再与后一个合并

** 将tmp中内容拷贝回原数组**
在这里插入图片描述

将间隔为gap的小区间归并后的内容整体拷贝回原数组

void MergeSort1(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail\n");return;}int gap = 1;while (gap < n){//小区间由gap控制,且每次都是前一个区间和后一个区间//归并为一个大的有序区间,所以每次i需要加上gap的2倍,//一次跳过两个区间for (int i = 0; i < n; i += 2*gap){//控制区间范围(数据个数)int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap-1;int j = i;//由于两个小区间要合并为一个区间,//然后存放到数组tmp中,合并后数组tmp长度大小//为两个小区间长度大小之和,然后下次在开始合并时,//从合并后的右端下标开始赋值,所以tmp下标起始由i//决定if (end1 >= n){end1 = n - 1;begin2 = n ;end2 = n-1;}else if (begin2 >= n){begin2 = n ;end2 = n-1;}else if(end2 >=n ){end2 = n - 1;}//两个区间中小的数尾插到tmp数组中while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}while (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}}//将间隔为gap小区间合并后的数组tmp里的内容全部拷贝回原数组中memcpy(a, tmp, sizeof(int) * n);gap *= 2;//最后gap变为原来的2倍}free(tmp);
}

将间隔为gap的小区间一段一段的拷贝回原数组

void MergeSort2(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail\n");return;}int gap = 1;while (gap < n){for (int i = 0; i < n; i += 2 * gap){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;int j = i;//由于gap使其分区间块化有序,此时前一个区间的右端//或者后一个区间的左端超出数组长度了,那么直接//拷贝到原数组后面if (end1 >= n || begin1 >= n){break;}else if (end2 >= n){end2 = n - 1;}while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}while (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}//每一次区间间隔为gap的两个区间合并后就将其拷贝到//原数组中memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));}gap *= 2;}free(tmp);
}

归并排序将两个有序的区间归并为一个有序的区间

相关文章:

算法之归并排序

文章目录一、归并排序&#xff08;递归版&#xff09;二、归并排序&#xff08;非递归版&#xff09;一、归并排序&#xff08;递归版&#xff09; 归并排序思想&#xff1a;将数组划分为两个区间&#xff0c;左区间&#xff0c;右区间 然后对这两个区间内容进行排序 &#xff…...

Mysql日志系统-mysql serve层

Mysql日志系统-服务层的日志 mysql给我们提供了很多有用的日志有mysql服务层提供的&#xff0c;有innodb引擎层提供的&#xff0c;下表是mysql服务层给我们提供的&#xff1a; 日志类型写入日志的信息二进制日志记录了对MySQL数据库执行更改的所有操作慢查询日志记录所有执行…...

阿里云蔡英华:云智一体,让产业全面迈向智能

4月11日&#xff0c;在2023阿里云峰会上&#xff0c;阿里云智能首席商业官蔡英华表示&#xff0c;算力的飞速发展使数字化成为确定&#xff0c;使智能化成为可能。阿里云将以云计算为基石&#xff0c;以AI为引擎&#xff0c;参与到从数字化迈向智能化的划时代变革中。 基于服务…...

打怪升级之FPGA组成原理(LE部分)

FPGA芯片逻辑单元的原理 不论你使用哪一款FPGA芯片&#xff0c;其核心可编程逻辑单元都是从一段内存种按顺序读取执行并执行的过程。具体来说&#xff0c;FOGA芯片内部包括可编程逻辑块(LAB)、可配置输入输出单元(IOE)、时钟管理模块、嵌入式RAM(BRAN&#xff0c;在Cyclone IV…...

c++的多态

目录 1、多态 1.1多态的构成条件 1.2多态的好处 2、虚函数 2.1虚函数重写 2.2虚函数的默认参数 2.3纯虚函数重写 2.4抽象类 2.5虚析构&#xff0c;纯虚析构重写 3、重载、覆盖(重写)、隐藏(重定义)的对比 ​编辑 多态是c面向对象三大特性之一 程序调用函数时&#…...

【数据结构与算法】堆的实现(附源码)

目录 一.堆的概念及结构 二.接口实现 A.初始化 Heapinit 销毁 Heapdestroy B.插入 Heappush 向上调整 AdjustUp 1.Heappush 2.AdjustUp C.删除 Heappop 向下调整 AdjustDown D.堆的判空 Heapempty 堆顶数据 Heaptop 堆的大小 Heapsize 三.源码 Heap.h He…...

win10彻底永久关闭自动更新【亲测有效】

一、禁用Windows Update服务 1、同时按下键盘 Win R&#xff0c;打开运行对话框&#xff0c;然后输入命令 services.msc &#xff0c;点击下方的“确定”打开服务&#xff0c;如下图所示。 2、找到 Windows Update 这一项&#xff0c;并双击打开&#xff0c;如图所示。 3、右击…...

【Unity UPR】造个获取深度法线纹理的轮子

描边需要深度法线纹理的加持&#xff0c;效果才能达到最好&#xff0c;但URP下很多版本不支持直接获取_CameraNormalsTexture&#xff0c;而我本人也尝试了一下在12.1.7下偷懒直接拿SSAO里的Depth Normal图&#xff0c; 虽然也能实现吧&#xff0c;但是需要打开SSAO的同时&…...

用 Python解析HTML页面

用 Python 解析 HTML 页面 在网络爬取的过程中&#xff0c;我们通常需要对所爬取的页面进行解析&#xff0c;从中提取我们需要的数据。网页的结构通常是由 HTML 标签所组成的&#xff0c;通过对这些标签的解析&#xff0c;可以得到网页中所包含的有用信息。在 Python 中&#…...

python logging 详解

python logging 详解1. 导入logging模块2. 配置日志记录器3. 记录日志消息4. 自定义日志记录器5. 日志轮换6. 日志过滤器7. 日志异常跟踪8. 日志输出到控制台和文件9. 使用配置文件10. 使用第三方库11. format格式详解12. 总结Python的logging模块提供了灵活的日志记录功能&…...

( “树” 之 DFS) 687. 最长同值路径 ——【Leetcode每日一题】

687. 最长同值路径 给定一个二叉树的 root &#xff0c;返回 最长的路径的长度 &#xff0c;这个路径中的 每个节点具有相同值 。 这条路径可以经过也可以不经过根节点。 两个节点之间的路径长度 由它们之间的边数表示。 示例 1: 输入&#xff1a;root [5,4,5,1,1,5] 输出&…...

Elasticsearch解决不能修改索引、字段问题解决方案

问题1&#xff1a; 由于es索引不能删除&#xff0c;不能修改&#xff0c;在不影响原数据的情况下&#xff0c;并且生产服务不停机的情况下&#xff0c;怎么修改索引&#xff0c;并保留原索引内的数据&#xff1f; 基于kibanna的dev Tools执行参数&#xff0c;淘汰postman&…...

面试官在线改简历 | 只有6秒!程序员简历这样写才能抓住科技公司大佬的眼球

其实每一份简历 每一个瑞库特 可能也就平均花6秒钟的时间看一看 来进行一个快速的筛选 一份好的简历到底应该长什么样 同时呢在我们写简历的过程当中 应该避免什么样子的错误和误区 那我们今天呢来聊聊这个简历的事 大家知道 每次到了招聘高分期啊这些大的公司 像谷歌Facebook…...

IM即时通讯-7-如何设计通知提醒

本文大纲 本文从为什么做通知提醒&#xff0c; 以及如何设计通知提醒&#xff0c; 以及如何衡量通知提醒三方面解释了如何设计通知提醒。 对于重点的如何设计通知提醒&#xff0c; 通过拆分前台和后台&#xff0c; 前台采用自建或者二方通道&#xff0c; 后台采用厂商信令通道…...

赛狐ERP | 亚马逊选品方法与策略详解:如何挑选最优质的产品?

亚马逊作为全球电商巨头&#xff0c;其产品种类之丰富也是无人能及。然而&#xff0c;在如此繁杂的商品体系下&#xff0c;如何选品成为了摆在商家面前的一道难题。本文将从亚马逊选品的目标、方法、策略三个方面进行详细介绍。 一、选品的目标 在进行选择之前&#xff0c;必…...

【GCU体验】基于PyTorch + GCU跑通ResNet50模型并测试GCU性能

一、环境 地址&#xff1a;启智社区:https://openi.pcl.ac.cn/ 二、计算卡介绍 云燧T20是基于邃思2.0芯片打造的面向数据中心的第二代人工智能训练加速卡&#xff0c;具有模型覆盖面广、性能强、软件生态开放等特点&#xff0c;可支持多种人工智能训练场景。同时具备灵活的可…...

【机器视觉------标定篇(二)】三点成圆算法(求相机旋转中心)

应用场景 机器视觉项目应用中&#xff0c;相机安装在机器人上&#xff0c;并且需要定位产品返回坐标偏差以及角度偏差。 与九点标定配合使用&#xff0c;实现精准角度补偿。 算法输入 不共线的三点坐标 A&#xff08;X₁,Y₁&#xff09; &#xff0c;B&#xff08;X₂,Y₂&…...

AUTOSAR E2E详细介绍

E2E概述 E2E(End-To-End)是AUTOSAR为功能安全ISO26262提出的一个安全模块。这里的端(End)并不是指ECU与ECU之间,而是指通信ECU上的SW-C与SW-C之间。 在车载网络中,信息交换通常是从一个ECU发送信号,另一个ECU接收信号。对E2E而言,通常是从源SW-C生成信号,经过RTE(R…...

Dream 主题使用手册 - 基础篇

Dream 主题基于 Halo 博客系统开发&#xff0c;本文将介绍本主题一些功能的使用&#xff0c;文档将持续更新。 一、安装 & 更新 1.1 安装包安装 & 更新 进入主题 Release 界面&#xff1a;https://github.com/nineya/halo-theme-dream/releases 下载主题压缩包 halo…...

WSL下的Kafka开发容器:Docker搭建、API、整合

背景介绍 Kafka是一个分布式流处理平台&#xff0c;可以处理大规模数据流并支持实时数据流的处理。 本文介绍了如何在WSL下使用Docker搭建Kafka容器&#xff0c;并使用Python的kafka-python库和FastAPI框架实现了一个简单的API。同时&#xff0c;还将该服务整合到一个整体的d…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...