排序篇(四)----归并排序

排序篇(四)----归并排序

1.归并(递归)

基本思想:
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

归并排序核心步骤:

在这里插入图片描述
在这里插入图片描述

//归并
void _MergeSort(int* a, int* tmp, int begin, int end)
{if (end <= begin){return;}int mid = (begin + end) / 2;_MergeSort(a, tmp, begin, mid);_MergeSort(a, tmp, mid + 1, end);// a->[begin, mid][mid+1, end]->tmp//归并int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int index = begin;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] <= a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}
//归并(递归版)
void MergeSort(int* a, int n)
{int* tmp = malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");exit(-1);}_MergeSort(a, tmp, 0, n - 1);free(tmp);
}

​ 归并需要开一个同样大的tmp数组来存放数据,相当于是拿空间来换时间了.

代码详解:

  1. 首先,将整个序列分为两部分,分别递归调用_MergeSort函数对左右两部分进行排序。
  2. 在_MergeSort函数中,首先判断递归终止条件,如果end小于等于begin,则表示当前子序列只有一个元素或者为空,无需排序,直接返回。
  3. 然后,计算中间位置mid,并分别递归调用_MergeSort函数对左右两部分进行排序。
  4. 接下来,进行归并操作。首先,设置四个指针begin1、end1、begin2、end2分别指向左右两部分的起始和结束位置,以及一个指针index指向当前归并结果的位置。
  5. 然后,使用两个循环比较左右两部分的元素大小,并将较小的元素放入tmp数组中,同时移动相应的指针。
  6. 最后,将剩余的元素复制到tmp数组中。
  7. 最后,将tmp数组中的元素复制回原数组a中,完成归并排序。

2.归并(非递归)

​ 非递归版是在递归上进行了修改,将其递归改为了循环.

//归并(非递归版)
void _MergeSortNotR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");exit(-1);}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;if (begin2 >= n){break;}if (end2 >= n){end2 = n - 1;}int index = i;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] <= a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}memcpy(a+i, tmp+i, (end2-i+1) * sizeof(int));}gap *= 2;}free(tmp);
}

代码详解:

​ 分配一个临时数组tmp,用于存储归并结果。

​ 然后,设置一个变量gap为1,表示归并的间隔大小。

接下来,循环执行以下操作,直到gap大于等于n:

  1. 遍历整个数组,每次取两个相邻的子序列进行归并。
  2. 计算左右两个子序列的起始和结束位置。
  3. 判断右子序列的结束位置是否超过了数组的长度,如果超过,则将结束位置设置为数组的最后一个元素的下标。
  4. 使用两个指针begin1和begin2分别指向左右两个子序列的起始位置,使用指针end1和end2分别指向左右两个子序列的结束位置。
  5. 使用一个指针index指向当前归并结果的位置。
  6. 使用一个循环,比较左右两个子序列的元素大小,并将较小的元素放入临时数组tmp中,同时移动相应的指针。
  7. 如果左子序列还有剩余元素,则将剩余元素复制到tmp数组中。
  8. 如果右子序列还有剩余元素,则将剩余元素复制到tmp数组中。
  9. 将tmp数组中的元素复制回原数组a中。
  10. 将gap乘以2,进行下一轮归并。

最后,释放临时数组tmp的内存空间。

归并排序的特性总结:

  1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(N)
    中的元素复制回原数组a中。
  4. 将gap乘以2,进行下一轮归并。

最后,释放临时数组tmp的内存空间。

归并排序的特性总结:

  1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(N)
  4. 稳定性:稳定

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

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

相关文章

Hive SQL初级练习(30题)

前言 Hive 的重要性不必多说&#xff0c;离线批处理的王者&#xff0c;Hive 用来做数据分析&#xff0c;SQL 基础必须十分牢固。 环境准备 建表语句 这里建4张表&#xff0c;下面的练习题都用这些数据。 -- 创建学生表 create table if not exists student_info(stu_id st…

yolov5分割+检测c++ qt 中部署,以opencv方式(详细代码(全)+复制可用)

1&#xff1a;版本说明&#xff1a; qt 5.12.10 opencv 4.5.3 &#xff08;yolov5模型部署要求opencv>4.5.0&#xff09; 2&#xff1a;检测的代码 yolo.h #pragma once #include<iostream> #include<cmath> #include<vector> #include <opencv2/…

毅速课堂:3D打印随形水路在小零件注塑中优势明显

小零件注塑中的冷却不均匀问题常常导致烧焦现象的发生。这主要是因为传统机加工方法无法制造出足够细小的水路&#xff0c;以适应小零件的复杂形状。而3D打印技术的引入&#xff0c;尤其是随形水路的设计&#xff0c;为解决这一问题提供了新的解决方案。 3D打印随形水路技术的优…

TS编译选项——编译TS文件同时对JS文件进行编译

一、允许对JS文件进行编译 我们在默认情况下编译TS项目时是不能编译js文件的&#xff0c;如下图中的hello.js文件并未编译到dist目录下&#xff08;这里配置了编译文件放到dist目录下&#xff09; 如果我们想要实现编译TS文件同时对JS文件进行编译&#xff0c;就需要在tsconfi…

使用U3D、pico开发VR(二)——添加手柄摇杆控制移动

一、将unity 与visual studio 相关联 1.Edit->Preference->External tool 选择相应的版本 二、手柄遥控人物转向和人物移动 1.添加Locomotion System组件 选择XR Origin&#xff1b; 2.添加Continuous Move Provider&#xff08;Action-based&#xff09;组件 1>…

编程每日一练(多语言实现)基础篇:求总数问题

文章目录 一、实例描述二、技术要点三、代码实现3.1 C 语言实现3.2 Python 语言实现3.3 Java 语言实现3.4 JavaScript 语言实现 一、实例描述 集邮爱好者把所有的邮票存放在三个集邮册中&#xff0c;在A册内存放全部的十分之二&#xff0c;在B册内存放不知道是全部的七分之几&…

MyBatis的一级缓存和二级缓存:原理和作用

MyBatis的一级缓存和二级缓存&#xff1a;原理和作用 引言 在数据库访问中&#xff0c;缓存是一种重要的性能优化手段&#xff0c;它可以减少数据库查询的次数&#xff0c;加快数据访问速度。MyBatis作为一款流行的Java持久层框架&#xff0c;提供了一级缓存和二级缓存来帮助…

基于Java的大学生就业招聘系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

【数据结构】排序算法(一)—>插入排序、希尔排序、选择排序、堆排序

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.直接插入排序 2.希尔排序 3.直接选择排…

OpenCV之分水岭算法(watershed)

Opencv 中 watershed函数原型&#xff1a; void watershed( InputArray image, InputOutputArray markers ); 第一个参数 image&#xff0c;必须是一个8bit 3通道彩色图像矩阵序列&#xff0c;第一个参数没什么要说的。关键是第二个参数 markers&#xff0c;Opencv官方文档的说…

全网最全Python系列教程(非常详细)---集合讲解(学Python入门必收藏)

&#x1f9e1;&#x1f9e1;&#x1f9e1;这篇是关于Python中集合的讲解&#xff0c;涉及到以下内容&#xff0c;欢迎点赞和收藏&#xff0c;你点赞和收藏是我更新的动力&#x1f9e1;&#x1f9e1;&#x1f9e1; 1、集合是什么&#xff1f; 2、集合应该怎么去定义&#xff1f…

搭建前端框架

在终端进入web目录&#xff0c;然后创建vuecrud工程 创建工程并引入ElementUI和axios手把手教学>传送门:VueCLI脚手架搭建

力扣 -- 718. 最长重复子数组

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int findLength(vector<int>& nums1, vector<int>& nums2) {int m nums1.size();int n nums2.size();//多开一行&#xff0c;多开一列vector<vector<int>> dp(m 1, ve…

Ghostscript 在 Linux 和 Windows 系统的应用与问题解决

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

背诵不等于理解,深度解析大模型背后的知识储存与提取

自然语言模型的背诵 (memorization) 并不等于理解。即使模型能完整记住所有数据&#xff0c;也可能无法通过微调 (finetune) 提取这些知识&#xff0c;无法回答简单的问题。 随着模型规模的增大&#xff0c;人们开始探索大模型是如何掌握大量知识的。一种观点认为这归功于 “无…

【ARMv8 SIMD和浮点指令编程】NEON 加载指令——如何将数据从内存搬到寄存器(其它指令)?

除了基础的 LDx 指令,还有 LDP、LDR 这些指令,我们也需要关注。 1 LDNP (SIMD&FP) 加载 SIMD&FP 寄存器对,带有非临时提示。该指令从内存加载一对 SIMD&FP 寄存器,向内存系统发出访问是非临时的提示。用于加载的地址是根据基址寄存器值和可选的立即偏移量计算…

计算机网络(一):概述

参考引用 计算机网络微课堂-湖科大教书匠计算机网络&#xff08;第7版&#xff09;-谢希仁 1. 计算机网络在信息时代的作用 计算机网络已由一种通信基础设施发展成为一种重要的信息服务基础设施计算机网络已经像水、电、煤气这些基础设施一样&#xff0c;成为我们生活中不可或…

网络协议--概述

1.2 分层 网络协议通常分不同层次进行开发&#xff0c;每一层分别负责不同的通信功能。一个协议族&#xff0c;比如TCP/IP&#xff0c;是一组不同层次上的多个协议的组合。 TCP/IP通常被认为是一个四层协议系统&#xff0c;如图1-1所示。每一层负责不同的功能&#xff1a; 1.链…

【Vue.js】使用Element中的Mock.js搭建首页导航左侧菜单---【超高级教学】

一&#xff0c;Mock.js 1.1 认识Mock.js Mock.js是一个用于前端开发中生成随机数据、模拟接口响应的 JavaScript 库。模拟数据的生成器&#xff0c;用来帮助前端调试开发、进行前后端的原型分离以及用来提高自动化测试效率 总结来说&#xff0c;Element中的Mock.js是一个用于…

ClassNotFoundException与NoClassDefFoundError

如果这springboot服务启动时两个报错同时出现&#xff0c;那大概率是依赖间冲突导致的 查资料发现是springcloud的依赖版本和springboot的依赖版本不兼容&#xff0c;顺藤摸瓜找到springcloud jar包中调用org.springframework.boot.context.properties.ConfigurationProperties…