归并排序java实现
来源:互联网 发布:淘宝爱逛街发布宝贝 编辑:程序博客网 时间:2024/06/08 21:25
归并排序
编辑
归并过程为:比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素b[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。来源于【百度百科】。
解读:归并排序可以简单理解为两个步骤
1、递归二分待排序序列,最终映射成一颗二叉树,二叉树的叶子节点为单个待排序元素。
2、合并有序序列,每一次合并,将产生一个有序序列。合并的原则是,从树的底层,兄弟节点进行合并。重点理解【归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。来源于百度百科。】
举例说明:
待排序序列 1,5,6,2,3,7,4
递归排序的拆分与合并实例图
(1,5,6,2,3,7,4) 根节点 第0层
/ \
/ \
/ \
(1,5,6,2) (3,7,4) 第1层
/ \ / \
/ \ / \
(1,5) (6,2) 3 (7, 4) 第2层
/\ /\ / \
/ \ / \ / \
1 5 6 2 7 4 第3层
那是如何进行合并的呢?从叶子节点所在层开始进行合并(兄弟节点之间的合并)
第3层 (1,5) (2,6) (4,7)
第2层 (1,2,5,6) (3,4,7)
第1层 (1,2,3,4,5,6,7)
上述就是归并排序的核心所在,通常我们使用递归来实现,运用递归的核心:1、重复工作;2:递归结束条件(很重要),比如归并排序的递归结束(退出)条件为待分元素只包含一个元素(本例中的startInx == endInx),源码所在地址:https://git.oschina.net/zhcsoft/StudyDemo.git,所在类路径:persistent.prestige.console.algorithm.MergeSort。
现给出源码:
package persistent.prestige.console.algorithm;/** * 归并排序 * @author dingwei2 * */public class MergeSort {public static void main(String[] args) {// TODO Auto-generated method stubtestMergeSort();//int[] a = new int[] {2,5,16,21,1,4,7,10,22 };//int[] tmp = new int[a.length];//merge(a,0,4,8, tmp);//testMerge();}/** * 测试案例 */public static void testMergeSort() {int[] a = new int[] {1,8,7,16,4,9,15,12};testMergeSort(a);int[] b = new int[] {1};testMergeSort(b);int[] c = new int[] {1,7,9,5,6,7,9};testMergeSort(c);}private static void testMergeSort(int[] a) {System.out.println("待排序序列:");for(int i : a) {System.out.print(i + " ");}System.out.println("");int[] tmp = new int[a.length];mergeSort(a, 0, a.length -1, tmp);System.out.println("排序后的序列:");for(int i : a) {System.out.print(i + " ");}System.out.println("");}/** * 归并排序, */public static final void mergeSort(int[] source, int startInx, int endInx, int[] tmp) {if( startInx != endInx ) { // startInx == endInx,说明不可再分// mid 所在的元素放在下半区 [startInx, mid) [mid,endInx]int mid = ((endInx - startInx ) >> 1) + 1 + startInx; mergeSort(source, startInx, mid - 1, tmp); // 将左边部分继续拆分 mid 所在元素放下半区 [startInx, mid)mergeSort(source, mid, endInx, tmp); // 将右边部分继续拆分 mid 所在元素放下半区 [mid,endInx]merge(source, startInx, mid, endInx, tmp);//为什么是放在这里呢?就是归并排序的第一阶段,就是拆分元成一个有序序列(包含单个元素)。分解后的的元素,其实可以看出如下图/* * 待排序序列 1,5,6,2,3,7,4 * 递归排序的拆分与合并实例图 * (1,5,6,2,3,7,4) 根节点 第0层 * / \ * / \ * / \ * (1,5,6,2) (3,7,4) 第1层 * / \ / \ * / \ / \ * (1,5) (6,2) 3 (7, 4) 第2层 * /\ /\ / \ * / \ / \ / \ * 1 5 6 2 7 4 第3层 * 那是如何进行合并的呢?从叶子节点所在层开始进行合并(合并孩子) * 第3层 (1,5) (2,6) (4,7) * 第2层 (1,2,5,6) (3,4,7) * 第1层 (1,2,3,4,5,6,7) * * * * */} // 如果不可分,则跳出递归(递归的出口在这里)(startInx == endInx)}/** * 归并排序的合并部分(合并两个有序序列) * @param a * @param stInx 开始合并下标 * @param midInx 中间位置 * @param endInx 结束下标 * @param tmp 临时空间,等于带排序长度,在一次归并排序中,共用一个临时空间。 * */public static final void merge(int[] a, int stInx, int midInx, int endInx, int[] tmp) {int alen = midInx > stInx ? midInx - stInx : 0;int blen = endInx - midInx + 1;int len = alen + blen;int aIndex = stInx;int bIndex = midInx;alen += stInx; //blen += midInx; // 这里主要是为了 aIndex < alen && bIndex < blen 服务的int al = 0;while( al < len ) {if(aIndex < alen && bIndex < blen) {if(a[ aIndex ] >= a[bIndex]) {tmp[al] = a[bIndex];bIndex ++;} else {tmp[al] = a[aIndex];aIndex ++;}} else if(aIndex < alen) {tmp[al] = a[aIndex];aIndex ++;} else {tmp[al] = a[bIndex];bIndex ++;}al++;}System.arraycopy(tmp, 0, a, stInx, len); // 将tmp拷贝到source数组,该部门元素的排序}/** * 先实现 合并算法,然后转换为 merge 方法的实现 * * 该方法为草稿类,主要合并两个已排序序列算法,进而演变为 merge(int[] a, int stInx, int midInx, int endInx, int[] tmp) * */public static final void testMerge() {int[] a = new int[]{ 1,4,7,10,22};int[] b = new int[] {2,5,16,21};int len = a.length + b.length;int[] c = new int[len];int aIndex = 0;int bIndex = 0;int al = 0;while( al < len ) {if(aIndex < a.length && bIndex < b.length) {if(a[ aIndex ] >= b[bIndex]) {c[al] = b[bIndex];bIndex ++;} else {c[al] = a[aIndex];aIndex ++;}} else if(aIndex < a.length) {c[al] = a[aIndex];aIndex ++;} else {c[al] = b[bIndex];bIndex ++;}al++;}for(int i : c ) {System.err.print(i + " ");}}}
对于一个包含n个元素的待排序序列,首先需要将排序序列分解成一颗二叉树,运算次数为 logn(2的对数)
然后合并操作,每一层进行归并运算的时候,需要比较元素的次数为n
所以算法复杂度为 n * logn
归并排序需要一个临时空间,所需要的空间为元序列的两倍。
- 归并排序Java实现
- Java实现归并排序
- Java实现归并排序
- 归并排序Java实现
- 归并排序JAVA实现
- java实现归并排序
- 归并排序(java实现)
- 归并排序java实现
- Java实现归并排序
- 归并排序 java实现
- 归并排序Java实现
- 归并排序java实现
- Java实现归并排序
- Java实现归并排序
- Java实现归并排序
- JAVA实现归并排序
- java实现归并排序
- 归并排序 Java实现
- 自学Java之Java类库(响应用户输入)(012day)
- C#字符串与unicode互相转换
- 收到客户还款记帐
- ThreadPoolExecutor使用介绍
- angularJs中指令介绍与用法
- 归并排序java实现
- Android 代替USB 调试的无线调试使用方法介绍
- C++读取txt中数据的两种方法
- JDK环境搭建
- 7.C/C++排序
- npm npmrc
- ceph基于令牌桶算法的image的流量IOPS上限限制
- ExpandableListView的使用解析
- jQuery中eq和get的区别