排序系列之-归并排序
2014-05-12 17:31
197 查看
排序系列之-归并排序
花了一下午时间,终于搞懂了归并排序,好记性不如烂笔头,搞懂了还是记下来吧,以后留着看,以后还能给人推荐看,也省去不少麻烦。言归正传,讲讲今天的内容,归并排序。
归并排序它是建立在归并的基础上的一种排序算法。
1.那么首先必须了解什么是归并。
归并是两个有序数组a,b,把它们按照该顺序,组合在一起。即a,b都是从小到大排序,那么组合成的数组,也是按从小到大排序。该算法思路:
new一个临时数组tmp,拿a数组的第一个数字和b数组的第一个数字作比较,假如b数组的第一个数字比a数组第一个数字小,就取b[0],并且添加到tmp中,然后拿b[1]和a[0]作比较,也是取最小的,然后循环获取2个数组中对应位置的最小的数字,最
终,会把某一个数组全部取完,假设a全部取完,那么剩下的b数组中的肯定都比取完的这些数字大,那么就把这些剩下的数字按顺序直接加入到tmp末尾,则归并结束。
归并的 java代码如下:
从最上面的图片一直使用二分法,对其进行拆分,拆到每份只有一个元素师再逆向合并。
思想就是如此,下面看java代码:
最后调用sort方法,拆分源数组,下标从0开始,到length-1
注释和讲解已经足够详细,相信大家都可以看懂了吧!
花了一下午时间,终于搞懂了归并排序,好记性不如烂笔头,搞懂了还是记下来吧,以后留着看,以后还能给人推荐看,也省去不少麻烦。言归正传,讲讲今天的内容,归并排序。
归并排序它是建立在归并的基础上的一种排序算法。
1.那么首先必须了解什么是归并。
归并是两个有序数组a,b,把它们按照该顺序,组合在一起。即a,b都是从小到大排序,那么组合成的数组,也是按从小到大排序。该算法思路:
new一个临时数组tmp,拿a数组的第一个数字和b数组的第一个数字作比较,假如b数组的第一个数字比a数组第一个数字小,就取b[0],并且添加到tmp中,然后拿b[1]和a[0]作比较,也是取最小的,然后循环获取2个数组中对应位置的最小的数字,最
终,会把某一个数组全部取完,假设a全部取完,那么剩下的b数组中的肯定都比取完的这些数字大,那么就把这些剩下的数字按顺序直接加入到tmp末尾,则归并结束。
归并的 java代码如下:
/** * 合并两个有序数组,返回合并后的数组 * @param a 有序数组a * @param b 有序数组b * @return 返回合并后的数组 */ public static int[] merger(int[] a,int len1,int[] b,int len2){ // int len1 = a.length; //数组a的长度 // int len2 = b.length; //数组b的长度 // int[] re = new int[len1 + len2]; int i = 0; //遍历数组a的时候使用的游标 int j = 0; //遍历数组b的时候使用的游标 int k = 0; //添加到re数组中使用的游标 while(i < len1 && j < len2){ if(a[i] < b[j]){ re[k++] = a[i++]; }else{ re[k++] = b[j++]; } } while(i <len1){ re[k++] = a[i++]; } while(j < len2){ re[k++] = b[j++]; } return re; }2.归并排序是采用分治的思想。讲数组对半分,一直分分分,分到只剩一个元素作为一个数组时,那么我们认为这个数组时有序的, 那么再回退,跟它的分下来的兄弟可以做归并,归并之后它还是有序的,在回退,一直会退到根数组(根数组时题目要排序的数组)的一半是,左边是有序的,右边是有序的, 继续合并,合并结束,源数组完成排序。下面看一幅图片,
从最上面的图片一直使用二分法,对其进行拆分,拆到每份只有一个元素师再逆向合并。
思想就是如此,下面看java代码:
/** * 讲源数组拆分为有序的数组 * @param src 源数组 * @param i 源数组的起始位置 * @param j 源数组的结束为止 */ public static void sort(int[] src,int i,int j){ if(i < j){ //只要一段数组起始位置i小于结束位置j,则说明它长度>1,则继续拆分 int mid = (i + j) / 2; sort(src,i,mid); //对左边的数组段[i,mid]进行有序化 sort(src,mid+1,j); //对右边的数组段[mid+1,j]进行有序化 mergerArray(src,i,mid,j); //合并两段有序数组 } } /** * 归并数组 * 两个数组分别为 数组的[s,mid],[mid+1,e]闭区间 * @param a 源数组 * @param s 源数组的起始位置 * @param mid 源数组的中间位置 * @param e 源数组的结束位置 */ public static void mergerArray(int[] a,int s,int mid ,int e){ if(s < e){ // 两个数组为两个数组时才归并 int i = s; int j = mid + 1; //建立一个临时数组,长度为e-s+1 int[] tmp = new int[e-s+1]; int k = 0;//k用来指示临时数组的当前存放元素下标 while(i <= mid && j <= e ){ //开始合并条件 if(a[i] < a[j]){ tmp[k++] = a[i++]; }else{ tmp[k++] = a[j++]; } } /*将剩余的未合并的添加到临时数组末尾*/ while(i <= mid){ tmp[k++] = a[i++]; } while(j <= e){ tmp[k++] = a[j++]; } //把临时数组复制会a[s,e]中 System.arraycopy(tmp,0,a,s,e-s+1); } }
最后调用sort方法,拆分源数组,下标从0开始,到length-1
int[] a = new int[]{7,3,2,9,23,10,15,12}; //源数组 sort(a,0,a.length-1); //对源数组进行排序
注释和讲解已经足够详细,相信大家都可以看懂了吧!
相关文章推荐
- LintCode刷题系列:数组排序--归并排序 递归
- 排序系列算法——归并排序
- 排序算法系列-堆排序-快速排序-基数排序-简单选择排序-归并排序
- 数据结构和算法系列8 七大排序之归并排序
- 数据结构与算法系列之一:八大排序之归并排序
- 每天学习算法系列—内部排序之归并排序和快速排序
- 排序总结系列六:归并排序
- 数据结构与算法从零开始系列:冒泡排序、选择排序、插入排序、希尔排序、堆排序、快速排序、归并排序、基数排序
- 【各种排序系列之】归并排序
- 傻瓜学算法系列之排序——4.归并排序
- 排序系列之归并排序
- 排序系列-归并排序
- lintcode刷题系列:链表排序----归并排序 递归
- 数据结构和算法系列8 七大排序之归并排序
- 排序系列之快速排序和归并排序
- 算法熟记-排序系列-归并排序
- 敏捷开发生态系统系列之三:计划跟踪II(需求优先级排序-迭代期内无变更-团队承诺)
- 九度OJ 1348:数组中的逆序对 (排序、归并排序)
- 常用内部排序算法之一:归并排序
- 基本排序之归并排序