如何使用递归实现归并排序
2015-03-18 18:32
447 查看
归并排序:归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide
and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
数据结构的学习过程中,我们经常会遇到排序算法,其中归并排序是一种高效并且算法复杂度比较简单的一种。在课本的介绍中,大部分都会介绍归并排序算法。但是,每次看书总是觉得很容易,自己尝试去实现时,总是会出错。学习数据结构已经有一段时间了,但是直接让我裸写归并排序的代码,也需要花上不少时间去调试。难道就没有更好的方式让我们记住代码吗?
其实只要我们在写代码时,注意下技巧,便可轻松实现归并排序算法。下面介绍下我使用的方式:
第一步:先写一个合并两个排序好数组的方法,方法名就叫做merge,如下:
这个方法非常简单,一共有着5个参数(也可以简化为3个参数),其中a,b数组是待合并数组,aSize,bSize是数组长度(这两个参数可以去掉),c为目标数组。主要的流程就是不断的比较a,b数组的大小,然后将较小数据复制进c中。这里面关键的一点就是使用了3个临时变量,用于标志每个数组对应的位置,这样子可以极大简化我们的代码设计。下面是对应的图示过程:
有了这个方法之后,我们就可以开始写归并排序的主体方法了。写主体方法也很简单,思想就是分治算法。
第一步:就是将大数组分成两个小的数组
第二部:排序这两个数组,使用的是递归排序方法,也就是自己调用自己
第三部:调用上面的合并方法合并起来即可
代码非常简单,直接贴上
总结:要记住归并排序算法的核心核心思想:分而治之。
and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
数据结构的学习过程中,我们经常会遇到排序算法,其中归并排序是一种高效并且算法复杂度比较简单的一种。在课本的介绍中,大部分都会介绍归并排序算法。但是,每次看书总是觉得很容易,自己尝试去实现时,总是会出错。学习数据结构已经有一段时间了,但是直接让我裸写归并排序的代码,也需要花上不少时间去调试。难道就没有更好的方式让我们记住代码吗?
其实只要我们在写代码时,注意下技巧,便可轻松实现归并排序算法。下面介绍下我使用的方式:
第一步:先写一个合并两个排序好数组的方法,方法名就叫做merge,如下:
public static void merge(int[] a, int aSize, int[] b, int bSize, int[] c){ int tempA = 0, tempB = 0, tempC = 0; while(tempA < aSize && tempB < bSize){ if(a[tempA] > b[tempB]){ c[tempC++] = b[tempB++]; }else{ c[tempC++] = a[tempA++]; } } while(tempA < aSize){ c[tempC++] = a[tempA++]; } while(tempB < bSize){ c[tempC++] = b[tempB++]; } }
这个方法非常简单,一共有着5个参数(也可以简化为3个参数),其中a,b数组是待合并数组,aSize,bSize是数组长度(这两个参数可以去掉),c为目标数组。主要的流程就是不断的比较a,b数组的大小,然后将较小数据复制进c中。这里面关键的一点就是使用了3个临时变量,用于标志每个数组对应的位置,这样子可以极大简化我们的代码设计。下面是对应的图示过程:
有了这个方法之后,我们就可以开始写归并排序的主体方法了。写主体方法也很简单,思想就是分治算法。
第一步:就是将大数组分成两个小的数组
第二部:排序这两个数组,使用的是递归排序方法,也就是自己调用自己
第三部:调用上面的合并方法合并起来即可
代码非常简单,直接贴上
public class TowersApp{ public static void main(String[] args){ int[] a = {1,1,0,1,1,5,3}; mergeSort(a); for(int i=0; i<a.length; i++){ System.out.print(a[i]); } } public static void mergeSort(int[] source){ //递归出口 if(source.length == 1) return; //将大数组分成两个小数组 int middle = source.length / 2; int[] left = new int[middle]; for(int i=0; i<middle; i++){ left[i] = source[i]; } int[] right = new int[source.length - middle]; for(int i=middle; i<source.length; i++){ right[i-middle] = source[i]; } //对数据进行排序(这里使用递归排序) mergeSort(left); mergeSort(right); //合并排序好的数据 merge(left, left.length, right, right.length, source); } public static void merge(int[] a, int aSize, int[] b, int bSize, int[] c){ int tempA = 0, tempB = 0, tempC = 0; while(tempA < aSize && tempB < bSize){ if(a[tempA] > b[tempB]){ c[tempC++] = b[tempB++]; }else{ c[tempC++] = a[tempA++]; } } while(tempA < aSize){ c[tempC++] = a[tempA++]; } while(tempB < bSize){ c[tempC++] = b[tempB++]; } } }
总结:要记住归并排序算法的核心核心思想:分而治之。
相关文章推荐
- 问题4:如何使用递归与非递归实现二分查找?
- 怎样使用递归实现归并排序
- 如何分别使用递归与非递归实现二分查找算法
- 如何使用循环而不是递归反推的方式实现拓展欧几里德算法
- 如何使用C语言实现递归调用
- MySQL使用递归存储过程实现树状结构,实现Oracle的Connect By 功能在Mysql中如何实现Oracle中的递归
- 不使用递归实现归并排序
- 如何分别使用递归与非递归实现二分查找算法
- 如何使用递归实现数据的累加
- C#如何不使用递归实现无限层次结构的代码分享[转]
- 数组的归并排序(经典实现:使用Ο(n)的辅助空间,递归)
- 使用"函数递归"实现基于php和MySQL的动态树型菜单
- 如何使用iframe实现calendar动态显示,
- 如何使用PB实现动态报表?
- 市面上所有号称"虚拟机","防火墙"的实时监控杀毒软件无一不是使用的IFSHOOK技术.但是同时也有一些朋友不断写MAIL给我打听如何实现读写的监控.下面给出用VTOOLSD写的代码.也就是所有实时杀毒软件的奥秘.同时,很多拦截文件操作的软件,例如对目录加
- 请问在.net framework精简版,使用C#语言如何实现MD5和SHA1算法
- 如何:使用回调方法实现异步 Web 服务客户端
- MSHFlexGrid1使用技巧(二)[如何让MSHFlexGrid实现点击列标题排序]
- 如何在Oracle中使用游标来实现多重循环?[原创]
- 如何实现登陆后,用户信息使用于多个站点?