【数据结构】八大排序之归并排序算法

🦄个人主页:修修修也

🎏所属专栏:数据结构

⚙️操作环境:Visual Studio 2022


目录

一.归并排序简介及思想

二.归并排序的代码实现

三.归并排序的非递归代码实现

四.归并排序的复杂度分析

📌时间复杂度

📌空间复杂度

结语


一.归并排序简介及思想

"归并"一词的中文含义就是合并,并入的意思,而在数据结构中的定义将两个或两个以上的有序表组合成一个新的有序表.

归并排序(Merging Sort)就是利用归并的思想实现的排序方法.

它的原理是:

       假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到\left \lceil \frac{n}{2} \right \rceil(\left \lceil x \right \rceil表示不小于x的最小整数)个长度为2或1的有序子序列;再两两归并,......,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序.

算法动图演示如下:

算法逻辑演示:


二.归并排序的代码实现

算法实现步骤:(以升序为例)

  1. 将数组中的n个数据看成n个有序子序列
  2. 然后将其两两归并到新数组内,得到\frac{n}{2}+1或\frac{n}{2}个长度为1或2的有序子序列,将新数组的数据拷贝回原数组.
  3. 重复步骤2,直到归并得到一个长度为n的有序序列为止.

综上,归并排序的代码实现如下:

//归并递归子函数
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, end1 = mid;int begin2 = mid + 1, end2 = end;int i = begin;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2])//循环将小值尾插进新数组{tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}//防止合并时有数组没拷贝完while (begin1 <= end1){tmp[i++] = a[begin1++];}while (begin2 <= end2){tmp[i++] = a[begin2++];}//拷贝tmp回原数组memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));}//归并排序
void MergeSort(int* a, int n)//不写区间,因为该函数不递归自己,否则每次都要malloc
{//开数组int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail::\n");return;}_MergeSort(a, 0, n - 1, tmp);//归并递归子函数free(tmp);
}

三.归并排序的非递归代码实现

算法实现思路:(以升序为例)

       因为归并排序递归是将完整的数组不断分割成只有一个元素的数组进行归并的,那么我们实现非递归的时候,就可以在一开始直接将数组视为n个只有一个元素的子序列进行归并,然后再按照两个两个元素的数组进行归并,一直向上归并,直到归并成为一个有n个元素的有序数组为止.

        归并排序在非递归实现时需要额外注意当n不是2的次方倍时归并数组末尾的越界现象,并对此错误现象做出及时的修正.

归并排序的非递归实现代码如下:

//归并排序非递归
void MergeSortNonR(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 =i+ 2 * gap){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;//修正数组非2的次方倍数时的越界现象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;}int j = i;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++];}}memcpy(a, tmp, sizeof(int) * n);gap *= 2;}free(tmp);
}

四.归并排序的复杂度分析

📌时间复杂度

从最开始的示意图我们可以看出,归并排序一趟总共处理n个元素,而总共要处理logn趟,因此归并排序的最好,最坏,以及平均时间复杂度都是一样的,那就是O(nlogn).


📌空间复杂度

而我们在排序过程中需要一个和原数组相同大小的临时数组来对数组进行归并排序,因此归并排序的空间复杂度为O(n).


结语

希望这篇归并排序算法详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

相关文章推荐

【数据结构】八大排序之冒泡排序算法

【数据结构】八大排序之希尔排序算法

【数据结构】八大排序之直接插入排序算法

【数据结构】八大排序之简单选择排序

【数据结构】八大排序之堆排序算法

【数据结构】八大排序之快速排序算法

【数据结构】八大排序算法之归并排序算法

数据结构排序算法篇思维导图:


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

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

相关文章

大文件快速传输解决办法汇总

在数据传输普及的当今时代&#xff0c;文件体量也在不断的突破它”大“的上线&#xff0c;很多企业也在面临着这类大文件快速传输的烦恼&#xff0c;而且这里面的“大”可不是一般意义的几M,几G的文件&#xff0c;它有可能上T级甚至是PB级别、TB级别的大文件&#xff0c;或者是…

前缀和算法 -- [模版]二维前缀和

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 本题链接 【模板】二维前缀和_牛客题霸_牛客网 输入描述 n是行&#xff0c;m是列&#xff0c;q是查询次数&#xff0c;x1&#xff0c;y1&#xff0c;x2&#xff0c;y2是二维数组的下标。 输出描述 通过两对下标&#x…

学习Java中的数据结构及API这一篇就够了

Java中的数据结构及API 1. 线性表1-1. 顺序表Array数组ArrayList集合 1-2. 链表自定义链表LinkedList 2. 队列2-1. ArrayDeque2-2. LinkedList2-3. 区别 3. 栈3-1. ArrayDeque3-2. LinkedList 4. 树4-1. 二叉树定义 5. 图5-1. 图定义 1. 线性表 1-1. 顺序表 顺序表是指用一组…

DDAE: Denoising Diffusion Autoencoders are Unified Self-supervised Learners

DDAE: Denoising Diffusion Autoencoders are Unified Self-supervised Learners Paper&#xff1a;https://arxiv.org/abs/2303.09769 Code&#xff1a;https://github.com/FutureXiang/ddae TL; DR&#xff1a;扩散模型的训练其实就是训练一个去噪模型&#xff0c;考虑到类似…

大数据概念:数据网格和DataOps

数据网格&#xff08;Data Mesh&#xff09; 一种新型的数据架构模式&#xff0c;旨在解决传统数据架构中存在的一些问题&#xff0c;例如数据孤岛、数据冗余、数据安全等。数据网格将数据作为一种服务&#xff0c;通过在分布式环境中提供数据服务&#xff0c;实现数据的共享和…

cJSON代码解读

1、背景 cJSON用了很久&#xff0c;但是对它一直不太了解。这次向添加对long long类型的支持&#xff0c;一直出问题。因为有以前添加两位小数float的经历&#xff0c;我觉得会很轻松&#xff0c;没想到翻车了。于是有了这边文档&#xff0c;阅读了部分博主对cJSON的解析&…

《动手学深度学习》学习笔记 第7章 现代卷积神经网络

本系列为《动手学深度学习》学习笔记 书籍链接&#xff1a;动手学深度学习 笔记是从第四章开始&#xff0c;前面三章为基础知识&#xff0c;有需要的可以自己去看看 关于本系列笔记&#xff1a; 书里为了让读者更好的理解&#xff0c;有大篇幅的描述性的文字&#xff0c;内容很…

挑战Python100题(9)

100+ Python challenging programming exercises 9 Question 81 Please write a program to randomly print a integer number between 7 and 15 inclusive. Hints: Use random.randrange() to a random integer in a given range. 请编写一个程序,随机打印一个介于7和15之间…

Redis(二)

1、redis的持久化 "Redis 如何将数据写入磁盘"&#xff0c;首先要明白的时候&#xff0c;我们使用的redis的数据保存在内存上的&#xff0c;也就是说&#xff0c;只要我们的电脑关机或者重启服务器&#xff0c;那么在内存中的数据就会消失&#xff0c;所以要想持久化…

【深度学习-基础学习】Transformer 笔记

本篇文章学习总结 李宏毅 2021 Spring 课程中关于 Transformer 相关的内容。课程链接以及PPT&#xff1a;李宏毅Spring2021ML这篇Blog需要Self-Attention为前置知识。 Transfomer 简介 Transfomer 架构主要是用来解决 Seq2Seq 问题的&#xff0c;也就是 Sequence to Sequence…

高压放大器的工作原理和使用方法是什么

高压放大器是一种用于产生高电压输出信号的电子设备&#xff0c;通常用于科学研究、医疗、工业和通信领域。它的工作原理涉及到电路设计、放大器拓扑结构、元件选型和功率供应等多个方面。下面将详细介绍高压放大器的工作原理和使用方法。 一、工作原理 放大器拓扑结构&#xf…

msvcp140.dll丢失的错误解决办法,msvcp140.dll丢失的原因

如果你的电脑中正处于msvcp140.dll丢失或找不到msvcp140.dll的问题&#xff0c;那么可以尝试使用下面的方法进行解决msvcp140.dll丢失的问题。其实msvcp140.dll文件丢失的问题解决办法也很简单&#xff0c;但是出现msvcp140.dll丢失的问题却可能是有很多原因。接下来就给大家分…