数据结构与算法系列——排序(10)_归并排序
1. 工作原理(定义)
归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,指的是将两个已经排序的序列合并成一个序列的操作。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:
- 自上而下的递归(所有递归的方法都可以用迭代重写,所以就有了第 2 种方法);
- 自下而上的迭代;
2. 算法步骤
1. 从下往上的归并排序【迭代】:
通过分治法将长度为n的序列划分为n个长度为1的子序列。
进行两两归并比较,得到 n/2 个长度为 2 的有序子序列
重复第 2 步,直到所有子序列归并成一个长度为 n 的有序序列。
2. 从上往下的归并排序【递归】:
分解 -- 将当前区间一分为二,即求分裂点 mid = (low + high)/2;
求解 -- 递归地对两个子区间a[low...mid] 和 a[mid+1...high]进行归并排序。递归的终结条件是子区间长度为1。
合并 -- 将已排序的两个子区间a[low...mid]和 a[mid+1...high]归并为一个有序的区间a[low...high]。
3. 归并步骤:
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
设定两个指针,最初位置分别为两个已经排序序列的起始位置;
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
重复步骤 3 直到某一指针达到序列尾;
将另一序列剩下的所有元素直接复制到合并序列尾。
3. 动画演示
4. 性能分析
1. 时间复杂度
归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要 logN 步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN),故时间复杂度为O(nlogn)。
2. 空间复杂度
归并排序过程中,需要一个辅助空间来暂存两有序子文件归并的结果,因此空间复杂度为O(n)。
3. 算法稳定性
归并是稳定的算法,在分解和并归过程中元素相对顺序未发生改变。
4. 初始顺序状态
- 比较次数:
- 移动次数:
- 复杂度:
- 排序趟数:
5. 归位
不能归位
6. 优点
- 排序:速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列
- 求逆序对数:在归并的过程中计算每个小区间的逆序对数,进而计算出大区间的逆序对数(也可以用树状数组来求解)
7. 具体代码
public class MergeSort {// 归并排序(从上往下,递归)public static void mergeSortUp2Down(int [] arr, int start, int end){if(arr!=null && start<end){//当子序列中只有一个元素时结束递归int mid=(start+end)/2;//划分子序列mergeSortUp2Down(arr, start, mid);//对左侧子序列进行递归排序mergeSortUp2Down(arr, mid+1, end);//对右侧子序列进行递归排序merge(arr, start, mid, end);//合并 }}//归并排序(从下往上,迭代)public static void mergeSortDown2Up(int [] arr){if(arr!=null){int len = arr.length;//gap表示有序数组的长度(1,2,4,8……)for(int gap = 1; gap < len; gap*=2){int i;// 将"每2个相邻的子数组" 进行合并排序。for(i = 0; i+2*gap-1 < len; i+=(2*gap)){merge(arr, i, i+gap-1, i+2*gap-1);}// 若 i+gap-1 < len-1,则剩余一个子数组没有配对。// 将该子数组合并到已排序的数组中。if (i+gap-1 < len-1){merge(arr, i, i+gap-1, len-1);}}}}//两路归并算法,两个排好序的子序列合并为一个子序列public static void merge(int []arr, int left, int mid, int right){int []tmp=new int[arr.length];//辅助数组int p1=left,p2=mid+1,k=left;//p1、p2是检测指针,k是存放指针while(p1<=mid && p2<=right){if(arr[p1]<=arr[p2])tmp[k++]=arr[p1++];elsetmp[k++]=arr[p2++];}while(p1<=mid) tmp[k++]=arr[p1++];//如果第一个序列未检测完,直接将后面所有元素加到合并的序列中while(p2<=right) tmp[k++]=arr[p2++];//同上//复制回原素组for (int i = left; i <=right; i++) arr[i]=tmp[i];}public static void main(String[] args){int[] arr = { 49, 38, 65, 97, 76, 13, 27, 50 };//mergeSortUp2Down(arr, 0, a.length-1); mergeSortDown2Up(arr);System.out.println("排好序的数组:");for (int e : arr)System.out.print(e+" ");} }
8. 参考网址
- 数据结构基础学习笔记目录
- 排序算法系列之并归排序
- 图解排序算法(四)之归并排序
- https://visualgo.net/en/sorting
- https://www.runoob.com/w3cnote/merge-sort.html
- https://github.com/hustcc/JS-Sorting-Algorithm
- 归并排序
- Java实现归并排序-有图有真相
转载于:https://www.cnblogs.com/haimishasha/p/10856561.html
数据结构与算法系列——排序(10)_归并排序相关推荐
- 数据结构与算法系列——排序(3)_折半插入排序
1. 工作原理(定义) 二分插入排序(Binary Insertion Sort,折半插入排序 OR 拆半插入排序),采用折半查找方法. 二分查找插入排序的原理:是直接插入排序的一个变种:区别是:在有 ...
- 数据结构排序算法实验报告_[数据结构与算法系列]排序算法(二)
我的上一篇文章向大家介绍了排序算法中的冒泡排序.插入排序和选择排序.它们都是平均时间复杂度为 O(n^2) 的排序算法,同时还为大家讲解了什么是原地排序和什么是排序的稳定性.下图是这三种算法的比较,不 ...
- 数据结构和算法之排序一:归并排序
我们不得不承认一个事实,java学习过程中如果我们掌握了各种编程手段和工具,确实可以做一些开发,这就是一些培训机构敢告诉你几个月就能掌握一门语言的原因.但是随着时间的发展,我们总会感觉,这一类人如果不 ...
- 希尔排序的详细过程_算法系列: 10大常见排序算法(4)希尔排序
本课程是从少年编程网转载的课程,目标是向中学生详细介绍计算机比赛涉及的编程语言,数据结构和算法.编程学习最好使用计算机,请登陆 www.3dian14.org (免费注册,免费学习). 一句 希尔排序 ...
- 导师计划--数据结构和算法系列(上)
导师计划已经开始一个月了,自己的讲解的课程选择了数据结构和算法.这个系列的讲解分为上下两章,javascript语言辅助.本篇文章为上章,涉及的内容是基本的数据结构.在日本,晚上没事安排@-@,时间还 ...
- 导师计划 -- 数据结构和算法系列(上)
导师计划已经开始一个月了,自己的讲解的课程选择了数据结构和算法.这个系列的讲解分为上下两章,javascript语言辅助.本篇文章为上章,涉及的内容是基本的数据结构.在日本,晚上没事安排@-@,时间还 ...
- 数据结构与算法(三) 排序算法(代码示例)
数据结构与算法三 排序算法 1. 选择排序 2. 插入排序 3. 冒泡排序 4. 归并排序 5. 快速排序 6. 希尔排序 7. 堆排序 总结 1. 选择排序 选择排序的基本原理: 对于未排序的一组记 ...
- 数据结构与算法之排序算法
数据结构与算法之排序算法 排序算法的介绍 排序也称排序算法(Sort Algorithm),排序是将一组数据,依指定的顺序进行排序的过程. 排序的分类 1)内部排序:指将需要处理的数据都加载到内部 ...
- 常见数据结构和算法实现(排序/查找/数组/链表/栈/队列/树/递归/海量数据处理/图/位图/Java版数据结构)
常见数据结构和算法实现(排序/查找/数组/链表/栈/队列/树/递归/海量数据处理/图/位图/Java版数据结构) 数据结构和算法作为程序员的基本功,一定得稳扎稳打的学习,我们常见的框架底层就是各类数据 ...
最新文章
- 深度学习必懂的 13 种概率分布(附链接)
- 霍夫变换直线检测理解
- php cache缓存 购物车,Yii2使用Redis缓存购物车等数据
- matlab多项式相乘的法则_卷积计算与多项式乘法
- 机柜服务器选择学问大!
- qt vs插件 qt-vsaddin下载
- 深入理解java虚拟机 (一) 第二版
- 二次元带音乐404源码
- 李永乐复习全书线性代数 第三章 向量
- 鸟哥的Linux私房菜基础学习篇 第2章的重点探索
- linux格式化u盘为ntfs格式,Linux上格式化U盘为NTFS格式
- storm源码分析研究(五)
- Python爬虫入门心得分享
- WSL 解决code .报‘code‘ not fount无法打开Vscode问题
- 网易云音乐的API接口及爬虫代码
- C语言复习03(小甲鱼版本)
- 【转】FAL_CLIENT和FAL_SERVER参数详解
- mysql数据库查询练习二-【比经理工资还高员工姓名】【查找重复的邮箱】
- 将IP地址更新到3323域名
- 加法的横式竖式教案c语言,20以内竖式加减法教案
热门文章
- Oracle回收站解决误删除表
- Git安装后安装目录改变
- php隔行符,PHP PHP_EOL 换行符
- 开源 RPC 框架有哪些
- pack unpack 用法 转载
- Lucene就是这么简单
- Web安全之点击劫持
- linux C(hello world)三个数最大和三个数最新
- [转载] 推荐的C++书籍以及阅读顺序
- mysql5.5启动报错:The server quit without updating PID file ([FAILED]localhost.localdomain.pid)....