十大排序算法之二路归并排序(难点为对于递归的理解)
归并排序(Merge Sort)算法思想:就是利用归并的思想实现排序的方法。
它的原理是假设初始序列有N个长度,则可以看成是N个有序的子序列,每个子序列的长度为1,然后两两归并,得到N/2个长度为2或1的有序子序列,再两两归并...如此重复,直至得到一个长度为N的有序序列为止,这种排序方法称为2路归并排序.
示例以及图片分析:
先将数组中的八个数全部分开成单个的八个数据(此时单个元素一定有序),再依次两两结合形成四对有序的数据组如图所示,再次两两结合形成两队有序的数据组(即为 4578 与 1236两个都是有序的数组),最后将这两个数组进行结合形成最终的有序数组.对于最后两队合成最终有序数组的过程为:
首先令4与1比较得最小数为1填入临时数组现有的第一个空格里面,之后再比较4与2得2为暂时的最小数据,按着前一个空格里面填入,不断继续比较,直到某个对里完全为空,将另一个对里面的数据按顺序全部填入临时数组即完成排序(例如7与6比完后直接将78填入了临时数组剩下的空中!)
代码如下:
package paixu;import java.util.Arrays;public class diGuiSort {public static void main(String[] args) {//原始待排序数组(无序的)int[] arr={10,30,2,1,0,8,7,5,19,29};//我们先给一个左右两边是有序的一个数组先来进行归并操作//int[] arr={4,5,7,8,1,2,3,6};//拆分之后就是可以不断调用归并函数(对半分)chaifen(arr,0,arr.length-1);//归并//guiBing(arr,0,3,arr.length-1);//输出原数组System.out.println(Arrays.toString(arr));}private static void chaifen(int[] arr, int startIndex, int endIndex) {//要先算出中间索引int centerIndex=(startIndex+endIndex)/2;if(startIndex<endIndex){chaifen(arr,startIndex,centerIndex);chaifen(arr,centerIndex+1,endIndex);guiBing(arr,startIndex,centerIndex,endIndex);}}private static void guiBing(int[] arr, int startIndex, int centerIndex, int endIndex) {//定义一个临时数组int[] tempArr = new int[endIndex-startIndex+1];//定义左边数组的起始索引int i=startIndex;//定义右边数组的起始索引int j=centerIndex+1;//定义临时数组的起始索引int index=0;//比较左右两个数组的元素大小,往临时数组中放while (i<=centerIndex&&j<=endIndex){if(arr[i]<=arr[j]){tempArr[index]=arr[i];i++;}else{tempArr[index]=arr[j];j++;}index++;}//再处理剩余元素while(i<=centerIndex){//左边数组有剩余元素就算等于centerIndex也是还有最后一个数据tempArr[index]=arr[i];i++;index++;}//要注意的是两个数组不可能都有剩余while(j<=endIndex){//右边数组有剩余元素就算等于endIndex也是还有最后一个数据tempArr[index]=arr[j];j++;index++;}//System.out.println(Arrays.toString(tempArr));//将临时数组中的元素取到原数组中;for(int k=0;k<tempArr.length;k++){arr[k+startIndex]=tempArr[k];//临时数组是从0开始传递过来的原数组是从startIndex开始}}}
首先对于方法guiBing(int[] arr, int startIndex, int centerIndex, int endIndex)为将确定的两个分组进行合并并且以合并后有序的顺序填入原数组中(借由中间数组),首先利用int[] tempArr = new int[endIndex-startIndex+1];定义一个对应两个分组之和大小的中间数组用来暂时存放排好序后的两个数组的序列,之所以用stratIndex,centerIndex,endIndex是因为调用时候分组大小是不确定的,所以用int型的形参来代替,之后按照上方自己所画图的方法进行循环比较,注意:循环判断条件为i<=centerIndex&&j<=endIndex即为每个分区只能在本分区内找数与另一分区的数进行比较,否则即为某分区内数已经找完(例如上方为由于j>endIdex的情况使循环退出),而循环内部的语句就是将找到的暂时最小的数不断由前向后填入临时数组的空格内,index=0就是用于不断填入临时数组(故而代码为判断arr[i]与arr[j]的大小若为arr[i]<=arr[j]则令arr[i]较小值填入tempArr[index];之后令i++(之后用左边数组的后面一个与j所代表的右边数组比较);与index++(令下次较小数填入临时数组的后方空格内),否则(>)则为将j代表元素填入tempArr[index]中并令j++;index++;)当此循环退出后即代表某个分区已经全部装入临时数组,有个分区仍未装入(至少还有一个元素且该分区仍为有序的,即大于临时数组中的所有数据,因此直接将其全部插入临时数组的末尾即可.)先看是否为左边元素未空,即while(i<=centerIndex)则不断将对应的arr[i]填入tempArr[index]中直到i>centerIndex为止,同理也要判断右边元素是否为空即while(j<=endIndex)同样的对右边剩余元素进行同样处理.此时已经两个分区排序完毕后全部装入临时数组,之后用for循环全部按顺序复制(赋值)到原数组arr中即可实现分区的合并并且能够体现在原数组中.之后的重点也就时难点就在于拆分方法的理解,对于最上方图片可以看出应该先进行拆分当拆分完成为均为一个的节点后便进行相邻两个同样大小分区的合并.此时涉及到递归的调用,用递归的方法,对于输入的一个初始数组,先调用 chaifen(arr,0,arr.length-1);进行拆分,而对于自己定义的chaifen方法则是先根据center递归调用表示将分成的两个分组也进行拆分即chaifen(arr,startIndex,centerIndex);与chaifen(arr,centerIndex+1,endIndex);之后就直接调用递归函数即可.实际理解可以根据对于某个实例的分析进行理解。具体如下图所示
理解如下对于其实长度为N的一个数组一定会因为递归的调用被逐渐分为大小为N/2的两个分区,N/4的四个分区....最终分为大小为1的N个分区,对于大小为一的分区也会调用cf(arr,num,num);但此时num=num;于是什么也不会执行,且由于为递归执行所在在所有的大小为1的分区为执行完之前都不会执行大小为2的分区,故而当执行大小为2的分区时就会执行guibing()函数也即是将大小为1的分区进行排序后合并放入原数组中,对于一个chaifen(arr,startIndex,endIndex)方法来说由函数体可得一定会执行其对应的guibing(arr,startIndex,centerIndex,endIndex)方法,故而会优先执行所有的大小为2的guibing方法(因为一旦有大小为4的方法想要执行一定会递归调用大小为2的chaifen方法)故而就实现了合并中从大小为1的分区逐渐两两合并最终合并为大小为N的有序数组,故而完成了此排序算法。
重难点:对于拆分过程的递归调用,从而实现先执行大小逐渐减小的拆分,再执行大小逐渐增大的合并,且对于合并来说当小的分区未完全合并之前,一定不会执行大的分区的合并,这就能实现第一个图片的思想.
十大排序算法之二路归并排序(难点为对于递归的理解)相关推荐
- 归并排序执行次数_十大排序算法,看这篇就够了
排序算法分类[1][2] 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序. 非比较类排序:不通过比较来决定元素间的相对次序,它可以 ...
- 数据结构与算法:十大排序算法之归并排序
数据结构与算法:十大排序算法之归并排序 package TopTenSortingAlgorithms;/*** 归并排序:Java** @author skywang* @date 2014/03/ ...
- 「干货总结」程序员必知必会的十大排序算法
点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:硬刚一周,3W字总结,一年的经验告诉你如何准备校招! 个人原创100W+访问量博客:点击前往,查看更多 绪论 身 ...
- 「归纳|总结」程序员必知必会的十大排序算法
微信搜一搜「bigsai」关注这个有趣的程序员 新人原创公众号,求支持一下!你的点赞三连肯定对我至关重要! 文章已收录在 我的Github bigsai-algorithm 欢迎star 本文目录 绪 ...
- 程序员必知必会的十大排序算法
绪论 身为程序员,十大排序是是所有合格程序员所必备和掌握的,并且热门的算法比如快排.归并排序还可能问的比较细致,对算法性能和复杂度的掌握有要求.bigsai作为一个负责任的Java和数据结构与算法方向 ...
- mysql外部排序算法_「干货总结」程序员必知必会的十大排序算法
绪论 身为程序员,十大排序是是所有合格程序员所必备和掌握的,并且热门的算法比如快排.归并排序还可能问的比较细致,对算法性能和复杂度的掌握有要求.bigsai作为一个负责任的Java和数据结构与算法方向 ...
- JS 实现十大排序算法
文章目录 前言 零.十大排序 一.冒泡排序(bubbleSort) 二.选择排序(selectionSort) 三.插入排序(insertSort) 四.希尔排序(shellSort) 五.归并排序( ...
- 程序员必备十大排序算法
程序员必备十大排序算法 常见排序算法 基本概念 插入排序 直接插入排序 排序思路 排序过程 代码实现 算法分析 折半插入排序 排序思路 排序过程 代码实现 算法分析 希尔排序 排序思路 排序过程 代码 ...
- 这或许是东半球分析十大排序算法最好的一篇文章
作者 | 不该相遇在秋天 转载自五分钟学算法(ID:CXYxiaowu) 前言 本文全长 14237 字,配有 70 张图片和动画,和你一起一步步看懂排序算法的运行过程. 预计阅读时间 47 分钟,强 ...
- 经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】
经典十大排序算法[Java版完整代码] 写在前面的话 十大排序算法对比 冒泡排序 快速排序 直接选择排序 堆排序 归并排序 插入排序 希尔排序 计数排序 桶排序 基数排序 完整测试类 写在前面的话 ...
最新文章
- 步步为营 .NET 设计模式学习笔记 六、Adapter(适配器模式)
- 四年上册级计算机教学计划,小学数学四年级上册教学计划
- systemd 对你的进程数限制横插一脚啦
- 一文带你了解MySQL基础
- 【双百解法】剑指 Offer 15. 二进制中1的个数
- 苹果手机耗电快_iPhone12用5G耗电快,苹果回应
- mybatis入门(六)之SQL语句构建器类
- Systemd 入门教程之命令篇
- php取到的时间总是差8小时的解决方法
- Android Add new target
- ctypes 传递opencv二值化图像给C++函数
- Kettle工具简单使用(spoon)
- 【智能路由器】轻量级web服务器lighttpd架设——打造家庭影院
- LINUX打包并下载到本地
- AI人工智能服务器安装说明书,AI人工智能电脑配置及服务器双显卡的安装总结...
- VP9编解码标准知识总结
- 付费小说服务器位置,黑科技学:听说好多听小说的都开始付费了?别担心好东西也能免费...
- 小米手机刷机工具MiFlash
- GMC解封秘籍:解决 Google 账户被封窘境
- 《修C传》——初始C语言 <凝气篇>
热门文章
- 大型计算机grads使用,win10中GRADS出现FAST_CWD pointer错误的详细解决方法
- 【雷达信号处理基础】第1讲 -- 雷达系统概述
- qqkey获取原理_通过call获取qqkey支持最新版
- Spring源码分析-Bean生命周期概述
- 代挂管家易开源7.4+web版
- 字节、十六进制字符串相互转换(asc2hex、hex2asc)
- docker核心视频教程
- 数据仓库是如何分层的?
- 电视盒刷linux 教程,网络机顶盒刷机教程和详细方法,实现软件任意安装,电视免费看...
- 深度学习剖根问底:SGD算法详解