归并算法详细解析

归并排序

1945年,约翰·冯·诺依曼(John von Neumann)发明了归并排序,这是典型的分治算法的应用。归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

基本思想

归并排序是使用分治算法,就是把序列分成长度相同的两个子序列,当无法继续往下分时(也就是每个子序列中只有一个数据时),就对子序列进行归并。归并指的是把两个排好序的子序列合并成一个有序序列。该操作会一直重复执行,直到所有子序列都归并为一个整体为止。

图形演示

为方便查看,我们用不同高度来表示不同的数字大小
在这里插入图片描述

  1. 首先我们把序列逐层对半分割

    在这里插入图片描述

直至不能再分割为止
在这里插入图片描述

  1. 分割完毕,接下来对每组元素进行合并;合并时需要将数字按照从小到大的顺序排列:
    在这里插入图片描述

每次合并时比较两个子序列的首位数字。当合并有多个数字的子序列时,要先比较首位数字,再移动较小的数字:由于3<4,所以要先移动3,接下来再比较4和7;4<7,所以移动4,再比较6和7…如此往复,左半个序列就排序好啦
在这里插入图片描述

右边也是如此,直至所有的数字都合并为一个整体为止
在这里插入图片描述

合并完成,序列的排序也就完成了

时间复杂度分析

​ 归并排序中,分割序列所花费的时间不算在运行时间内(可以当作序列本来就是分 割好的)。在合并两个已排好序的子序列时,只需重复比较首位数据的大小,然后移动较 小的数据,因此只需花费和两个子序列的长度相应的运行时间。也就是说,完成一行归 并所需的运行时间取决于这一行的数据量。 看一下上面的图便能得知,无论哪一行都是 n 个数据,所以每行的运行时间都为 O(n)。 而将长度为 n 的序列对半分割直到只有一个数据为止时,可以分成 log2n 行,因此,总 共有 log2n 行。也就是说,总的运行时间为 O(nlogn),这与前面讲到的堆排序相同。

代码实现

迭代法

public static void merge_sort(int[] arr) {int len = arr.length;int[] result = new int[len];int block, start;for(block = 1; block < len*2; block *= 2) {for(start = 0; start <len; start += 2 * block) {int low = start;int mid = (start + block) < len ? (start + block) : len;int high = (start + 2 * block) < len ? (start + 2 * block) : len;int start1 = low, end1 = mid;int start2 = mid, end2 = high;while (start1 < end1 && start2 < end2) {result[low++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];}while(start1 < end1) {result[low++] = arr[start1++];}while(start2 < end2) {result[low++] = arr[start2++];}}int[] temp = arr;arr = result;result = temp;}result = arr;       
}

递归法

static void merge_sort_recursive(int[] arr, int[] result, int start, int end) {if (start >= end)return;int len = end - start, mid = (len >> 1) + start;int start1 = start, end1 = mid;int start2 = mid + 1, end2 = end;merge_sort_recursive(arr, result, start1, end1);merge_sort_recursive(arr, result, start2, end2);int k = start;while (start1 <= end1 && start2 <= end2)result[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];while (start1 <= end1)result[k++] = arr[start1++];while (start2 <= end2)result[k++] = arr[start2++];for (k = start; k <= end; k++)arr[k] = result[k];
}public static void merge_sort(int[] arr) {int len = arr.length;int[] result = new int[len];merge_sort_recursive(arr, result, 0, len - 1);
}

总结

​ 归并排序与选择排序一样,性能不受输入数据的影响,但时间复杂度远小于选择排序。但由于归并排序需要另外一个与原数组长度相同的数组来做辅助排序,需要占用额外的空间,空间复杂度为O(n);

参考资料:《我的第一本算法书》

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

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

相关文章

公司系统中了.rmallox勒索病毒如何恢复数据?

早晨上班时刻&#xff1a; 当阳光逐渐洒满大地&#xff0c;城市的喧嚣开始涌动&#xff0c;某公司的员工们纷纷踏入办公大楼&#xff0c;准备开始新的一天的工作。他们像往常一样打开电脑&#xff0c;准备接收邮件、查看日程、浏览项目进展。 病毒悄然发作&#xff1a; 就在员…

Python学习:元组

Python 元组概念 Python 中的元组&#xff08;tuple&#xff09;是不可变的有序集合。它是一种数据类型&#xff0c;类似于列表&#xff08;list&#xff09;&#xff0c;但在创建后不能被修改。元组使用圆括号 () 来表示&#xff0c;其中的元素可以是任意类型&#xff0c;并且…

“洞见·智领未来——2024行业开局暨成渝(内江)服务外包产业发展大会”共商服务外包新未来新业态

3月19日-20日&#xff0c;由中国信息协会、中共内江市委、内江市人民政府指导&#xff0c;中国信息协会数字经济专委会、中共内江市东兴区委、内江市东兴区人民政府共同主办&#xff0c;鸿联九五集团、首席客户官百人会&#xff08;CCO100&#xff09;承办的“洞见 智领未来—…

Spring学习记录之注解开发

前面我们已经了解了Spring是如何创建Bean以及完成依赖注入的&#xff0c;但我们会发现&#xff0c;其似乎并没有达到简化开发的目的&#xff0c;这是因为 我们还没有接触到注解开发。 注解开发之组件 我们在要使用Bean的地方使用Comonpent&#xff08;组件&#xff09;注解&a…

Linux 文件系统:重定向、缓冲区

目录 一、重定向 1、输出重定向 2、输入重定向 3、追加重定向 4、dup2 系统调用 二、理性理解Linux系统下“一切皆文件” 了解硬件接口 三、缓冲区 1、为什么要有缓冲区? 2、刷新策略 3、缓冲模式改变导致发生写时拷贝 未创建子进程时 创建子进程时 使用fflush…

某招聘系统0day挖掘(获取4站点报告证书)

前言: 21年的挖的漏洞了 漏洞均已提交且均已修复,这里文章只做技术交流 挖掘过程 对我来说,毕竟喜欢直接黑盒挖0day,一个0day挖到后就可以刷上百分。 如该系统正常找了一个招聘系统用的比较多的 如该通用系统,该通用系统存在一个注册功能 正常的进行注册一个账户进去…

算法打卡day11

今日任务&#xff1a; 1&#xff09;239. 滑动窗口最大值 2&#xff09;347.前 K 个高频元素 239. 滑动窗口最大值 题目链接&#xff1a;239. 滑动窗口最大值 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移…

Windows 11 鼠标右键可选择 cmd 命令行选项

** Windows 11 鼠标右键可选择 cmd 命令行选项 ** 在文件夹内打开命令行&#xff0c;只能使用 Windows 自带的 PowerShell &#xff0c; 作为一个 cmd 重度使用用户来说很是折磨&#xff0c;需要打开 cmd 然后切换盘符再 cd 。。。 现在咱们自己创建一个可以打开 cmd 的方法…

【Leetcode每日一题】 递归 - Pow(x, n)(难度⭐⭐)(40)

1. 题目解析 题目链接&#xff1a;50. Pow(x, n) 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 在这个算法中&#xff0c;递归函数的任务是求出 x 的 n 次方。那么&#xff0c;这个函数是怎么工作的呢&#xff1f;它…

关于Devin,它只是人类历史的一个正常延续而已

近期&#xff0c;关于Devin的讨论无疑成为了科技界的热点话题。作为一款由初创公司Cognition AI研发的AI程序员&#xff0c;Devin凭借其惊人的“端到端解决成功率”和高效完成需求的能力&#xff0c;在各大社交媒体和科技论坛上引发了广泛的讨论。然而&#xff0c;在这场看似前…

LeetCode刷题记录:(13)N皇后(难题不难)

leetcode传送通道 传说中的N皇后&#xff0c;不难&#xff0c;进来了就看完吧 注释序号代表鄙人写代码的顺序和思考逻辑&#xff0c;供参考 class Solution {// 1.定义结果数组List<List<String>> result new ArrayList<>();public List<List<String&…

Learn OpenGL 23 阴影映射

阴影 阴影是光线被阻挡的结果&#xff1b;当一个光源的光线由于其他物体的阻挡不能够达到一个物体的表面的时候&#xff0c;那么这个物体就在阴影中了。阴影能够使场景看起来真实得多&#xff0c;并且可以让观察者获得物体之间的空间位置关系。场景和物体的深度感因此能够得到…