数据结构:归并排序

归并排序

时间复杂度O(N*logN)

如果两个序列有序,通过归并,可以让两个序列合并后也有序,变成一个有序的新数组

对于一个数组,如果他的左右区间都有序,就可以进行归并了

归并的方法

将数组的左右两个有序区间比较,每次都取出一个最小的,然后放入临时数组(不能在原数组上修改,因为修改原数组需要挪动数据,时间复杂度高)

但是对于任意一个数组而言,他的左右区间并不有序,如果想要使用归并排序,就要想办法取出数组的有序区间

这里可以使用递归拆分数组,当数组足够小(每一个区间都只有一个数据时),该区间就一定有序,就可以使用归并排序了

可以设置一个temp数组,用来存储分解的区间并进行排序,归并排序完成后再将temp拷贝回原数组的对应区间,直到递归完全结束(原数组有序)

代码

void _MergeSort(int* a, int begin, int end, int* tmp)
{if (begin == end)return;int mid = (begin + end) / 2;//开始递归_MergeSort(a, begin, mid, tmp);_MergeSort(a, mid + 1, end, tmp);//归并int begin1 = begin;int end1 = mid;int begin2 = mid + 1;int end2 = end;int i = begin;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}//判断哪个区间全部放入tmp,再将另一个区间全部放入tmpwhile (begin1 <= end1){tmp[i++] = a[begin1++];}while (begin2 <= end2){tmp[i++] = a[begin2++];}//将归并好的区间拷贝会原数组memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail!");return;}_MergeSort(a, 0, n - 1, tmp);//释放tmpfree(tmp);tmp = NULL;
}

归并排序的非递归方法

归并排序需要将递归改为循环

不方便使用栈来实现,因为不同于快速排序类似前序遍历,归并排序的递归类似于二叉树的后序遍历

问题核心

归并排序需要两个区间进行归并,

而如果使用栈,则当取到需要归并的两个区间的第二个

第一个区间就已经被pop出栈了,无法知道哪个区间需要和当前区间归并

解决方法

可以将数组看作一个一个数(一个数就是一个区间),然后每两个就进行归并

将归并后的两个数再看作一个区间,再与其他区间进行归并

即直接从叶子节点向前走(回溯)

可以设置gap = 2^n来归并每组数据

设置每个区间的首尾为b n(begin n),e n(end n)

eg.

由图可知,e1 = b1 + gap - 1,b2 = b1 + gap

后续同理

基础代码框架(存在问题)

根据当前的思路,可以写出大概的代码

void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}int gap = 1;while (gap < n)//一直归并到原数组大小{for (int j = 0; j < n; j += 2 * gap)//保证每一个区间都被取到{int begin1 = j, end1 = j + gap - 1;int begin2 = j + gap, end2 = begin2 + gap - 1;int i = j;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}//判断哪个区间全部放入tmp,再将另一个区间全部放入tmpwhile (begin1 <= end1){tmp[i++] = a[begin1++];}while (begin2 <= end2){tmp[i++] = a[begin2++];}memcpy(a + j, tmp + j, sizeof(int) * 2 * gap);}gap *= 2;}free(tmp);tmp == NULL;
}

代码问题(数组越界)

当前代码可能存在数组的越界访问

理论上来讲,除了begin1 = j < n外,其他的begin2, end1, end2都可能越界

因此需要分开处理这些问题

1.end1越界

end1越界(end1后面就没有数据了)说明当前没有第二组数据,而第一组只有一部分,且有序

因此当前这一组就不需要再进行归并了,直接让这一组准备下一层归并

2.begin2越界

begin2越界也不用归并,原因与end1越界相同

3.end2越界

end2越界需要归并,因为在begin2与end2中还存在部分有序数据,因此需要归并组成新区间

但是想要归并就需要修正end2,保证end2不再越界

4.修改后的代码

void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}int gap = 1;while (gap < n)//一直归并到原数组大小{for (int j = 0; j < n; j += 2 * gap)//保证每一个区间都被取到{int begin1 = j, end1 = j + gap - 1;int begin2 = j + gap, end2 = begin2 + gap - 1;int i = j;if (end1 >= n || begin2 >= n)//end1和begin2越界,跳出当前循环,不归并{break;}if (end2 >= n){end2 = n - 1;}while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}//判断哪个区间全部放入tmp,再将另一个区间全部放入tmpwhile (begin1 <= end1){tmp[i++] = a[begin1++];}while (begin2 <= end2){tmp[i++] = a[begin2++];}memcpy(a + j, tmp + j, sizeof(int) * (end2 - j + 1));//使用修正后的区间长度}gap *= 2;}free(tmp);tmp == NULL;
}

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

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

相关文章

PermissionError: [WinError 5] 拒绝访问。: ‘..\\data‘ 怎么解决

问题 在b站跟着沐神学深度学习&#xff0c;刚开始就遇到问题了&#xff0c;代码如下&#xff1a; import osos.makedirs(os.path.join(..,data),exist_okTrue) data_fileos.path.join(..,data,house_tiny.csv) with open(data_file,w) as f:f.write(NumRooms,Alley,Price\n)f…

空间数据结构(四叉树,八叉树,BVH树,BSP树,K-d树)

下文参考&#xff1a;https://www.cnblogs.com/KillerAery/p/10878367.html 游戏编程知识课程 - 四分树(quadtree)_哔哩哔哩_bilibili 利用空间数据结构可以加速计算&#xff0c;是重要的优化思想。空间数据结构常用于场景管理&#xff0c;渲染&#xff0c;物理&#xff0c;…

【过度拟合?秒了!】

目录 引言 一、简化模型复杂度 1 .1 特征选择 1.2 降低多项式阶数 1.3 减少神经元数量或层数 二、使用正则化技术 2.1 L1正则化&#xff08;Lasso&#xff09; 工作原理 应用场景 2.2 L2正则化&#xff08;Ridge&#xff09; 2.3 Elastic Net正则化 2.4 代码事例 …

国内如何购买midjourney?midjourney购买教程?midjourney注册方式?

1. Midjourney介绍 Midjourney 是一款备受欢迎的人工智能生成图像工具&#xff0c;它可以通过输入文字描述&#xff0c;自动生成精美的图像。与许多其他图像生成工具不同&#xff0c;Midjourney 不需要安装任何软件&#xff0c;也不受个人电脑性能的限制&#xff0c;因为它运行…

【测试篇】测试眼里的 BUG

文章目录 如何描述一个bug如何定义 bug 的级别BUG 的生命周期跟开发起争执怎么办&#xff08;高频面试题&#xff09; 如何描述一个bug 一个合格的bug描述应该包含以下几个部分&#xff1a; 发现问题的版本问题出现的环境错误重现的步骤预期行为的描述错误行为的描述其他&…

USB-PD

这是目录 写在前面1、概览2、信息2.1 消息结构2.1.1 消息头 3、soft or hard reset1、soft reset2、hard reset 3、TYPE-C相关握手3.1、CC线的状态3.1.1、默认电源值3.2 TYPE-C设备握手协商过程确定握手类型DRP和DRP设备握手 写在前面 1、记录自己的学习PD协议层的文章 1、概…

消息队列经典应用场景

笔者心中,消息队列,缓存,分库分表是高并发解决方案三剑客。 在职业生涯中,笔者曾经使用过 ActiveMQ 、RabbitMQ 、Kafka 、RocketMQ 这些知名的消息队列 。 这篇文章,笔者结合自己的真实经历,和大家分享消息队列的七种经典应用场景。 1 异步&解耦 笔者曾经负责某电…

00、SpringBatch 4.x.x版本:简单入门

00、SpringBatch批处理 一、介绍1、什么是批处理&#xff1f;2、官网3、优势4、组织架构5、程序运行架构图 二、入门案例-H2版(内存)1、新建项目2、引入依赖3、新建HelloJob.java 三、入门案例-MySQL版1、引入依赖2、修改 application.yml3、验证 四、案例解析1、EnableBatchPr…

国产桌面操作系统统一身份认证及2FA双因子认证安全升级方案

某金融运营服务公司&#xff0c;主要负责业务处理、客户服务、业务监控、报表统计等金融运营服务&#xff0c;为集团下设二级单位&#xff0c;坐落于一线城市&#xff0c;对政策风向有很高的敏锐度。 该公司已为公司业务人员、客户服务、监督员等配备了数百台国产桌面操作系统…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之七 简单图像浮雕效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之七 简单图像浮雕效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之七 简单图像浮雕效果 一、简单介绍 二、简单图像浮雕效果实现原理 三、简单图像浮雕效果案例实现简单步骤 四、注…

网络七层模型之会话层:理解网络通信的架构(五)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【豫都故郡·领航新篇】Springer独立出版 |第二届先进无人飞行系统国际会议(ICAUAS 2024)

会议简介 Brief Introduction 2024年第二届先进无人飞行系统国际会议(ICAUAS 2024) 会议时间&#xff1a;2024年6月14日-16日 召开地点&#xff1a;中国南昌 大会官网&#xff1a;ICAUAS 2024-2024 2nd International Conference on Advanced Unmanned Aerial Systems2024 2nd …

【C++】力扣-415-字符串相加(双指针,图例详解!!!)

目录 一、前言 二、字符串相加 三、共勉 一、前言 最近春招已经开始&#xff0c;看周围的同学都在投递一些大厂的实习&#xff0c;某为的手撕代码 --- 字符串相乘&#xff0c;某讯的手撕代码 --- 字符串相减等。 于是专门去 Leetcode 上搜索了一下&#xff0c;发现这类题目是面…

conda使用记录

linux 使用conda创建新一个新的python环境过程 conda create -n recommendation_env python3.8.18 # 指定python版本 conda env list # 查看所有的环境 conda activate recommendation_env # 激活创建的新环境 pip install flask # 安装依赖 或者 pip install flask版本号 或者…

脑机交互,屏幕是必须?No!让机器人发出激光光点实现脑机接口交互

一般说来&#xff0c;传统脑机接口(BCI)系统的交互过程依靠一个图形化的用户界面&#xff0c;不利于设备的便携性。而一种无屏幕的BCI可以通过让机器人在外界环境中发出刺激从而实现更直接的命令其中机器人使用激光光点凸显环境中的候选对象&#xff0c;而用户的目标则从脑电图…

跳跃游戏-java

题目描述: 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 解题思想: …

AIGC新潮流!手势灵动数字人视频、百变模特服装图、3D模型纹理一键生成

1、营销应用:AI生成生成带手势(手部动作)的数字人视频 (1)一个基于扩散模型的数字人生成框架,专注于生成具有全身动作的主播风格视频。该系统通过仅需一分钟的个人视频片段进行训练,便能自动生成具有精确躯干和手部动作的主播风格视频。 (2)定位:该框架定位于解决现…

docker环境配置过程中的常见问题

1、pull镜像问题 docker pull jenkins/jenkins:lts Using default tag: latest Trying to pull repository docker.io/library/centos ... Get https://registry-1.docker.io/v2/library/centos/manifests/latest: Get https://auth.docker.io/token?scoperepository%3Alibr…

自动驾驶-如何进行多传感器的融合

自动驾驶-如何进行多传感器的融合 附赠自动驾驶学习资料和量产经验&#xff1a;链接 引言 自动驾驶中主要使用的感知传感器是摄像头和激光雷达&#xff0c;这两种模态的数据都可以进行目标检测和语义分割并用于自动驾驶中&#xff0c;但是如果只使用单一的传感器进行上述工作…

数据处理库Pandas数据结构DataFrame

Dataframe是一种二维数据结构&#xff0c;数据以表格形式&#xff08;与Excel类似&#xff09;存储&#xff0c;有对应的行和列&#xff0c;如图3-3所示。它的每列可以是不同的值类型&#xff08;不像 ndarray 只能有一个 dtype&#xff09;。基本上可以把 DataFrame 看成是共享…