递归和迭代两种方式实现归并排序(Java版)

递归版

package MergeSort;

import Utils.SortUtils;
/**
 * 归并排序递归版
 * @author liguodong
 */

public class Demo02 {

    public static void mergeSort(int[] a){
        mSort(a, a, 0, a.length-1);
    }
    /**
     *
     * @param SR为待排序的数据
     * @param TR1为排序之后的数据
     * @param s
     * @param t
     */
    public static void mSort(int[] SR,int[] TR1, int s,int t){
        int m;
        int[] TR2 = new int[SR.length];

        if(s==t){
            TR1[s] = SR[s];
        }else {
            m = (s+t)/2;//4
            mSort(SR, TR2, s, m);
            mSort(SR, TR2, m+1, t);
            merge(TR2, TR1, s, m, t);//0 4 8
        }

    }

    //归并两个有序的数组
    /**
     * @param SR 有两个有序数组
     * @param TR 将SR的两个有序数组合并为一个数组TR
     * @param i
     * @param m
     * @param n
     */
    public static void merge(int[] SR,int[] TR,int i,int m,int n){
        int j,k,l;

        //i(0~4) j(5~8)
        for(j=m+1,k=i; i<=m && j<=n; k++){

            if(SR[i]<SR[j]){
                TR[k] = SR[i++];
            }else{
                TR[k] = SR[j++];
            }
        }

        if(i<=m){
            for (l = 0; l <= m-i ; l++) {
                TR[k+l] = SR[i+l];
            }
        }

        if(j<=n){
            for (l = 0; l <= n-j; l++) {
                TR[k+l] = SR[j+l];
            }
        }
    }

    public static void main(String[] args) {
        int[] a = {2,3,5,4,1,6,9,8,7};
        mergeSort(a);
        SortUtils.printString(a);
    }
}

复杂度分析

迭代版

package MergeSort;
import Utils.SortUtils;

/**
 * 递归排序迭代版
 * @author liguodong
 *
 */

public class Demo03 {

    public static void mergeSort(int[] a){
        int[] TR = new int[a.length];//用于存放归并结果

        int k=1;//起始,子序列长度为1
        while(k<a.length){
            mergePass(a, TR, k, a.length);//将原先无序的数据两两归并入TR
            k = 2*k;//子序列长度加倍
            mergePass(TR, a, k, a.length);//将TR中已经两两归并的有序序列再归并回数组a
            k = 2*k;//子序列长度加倍
        }
    }

    public static void mergePass(int[] SR, int [] TR,int s,int len){

        int i=0;
        while (i < len-2*s+1) {//8
            merge(SR,TR,i,i+s-1,i+2*s-1);//两两归并
            i=i+2*s;
        }

        //处理最后的尾数
        //i=8
        if(i< len-s+1){//9
            merge(SR, TR, i, i+s-1, len-1);//归并最后两个序列
        }else {
            for (int j = i; j < len; j++) {//若最后只剩下单个子序列
                TR[j] = SR[j];
            }
        }
    }

    public static void merge(int[] SR,int[] TR,int i,int m,int n){
        int j,k,l;

        //i(0~4) j(5~8)
        for(j=m+1,k=i; i<=m && j<=n; k++){

            if(SR[i]<SR[j]){
                TR[k] = SR[i++];
            }else{
                TR[k] = SR[j++];
            }
        }

        if(i<=m){
            for (l = 0; l <= m-i ; l++) {
                TR[k+l] = SR[i+l];
            }
        }

        if(j<=n){
            for (l = 0; l <= n-j; l++) {
                TR[k+l] = SR[j+l];
            }
        }
    }

    public static void main(String[] args) {
        int[] a = {2,3,5,4,1,6,9,8,7,10,20,45,32,28,44,31,55,43,23,21,23,21,33,21};
        mergeSort(a);
        SortUtils.printString(a);
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 22:34:12

递归和迭代两种方式实现归并排序(Java版)的相关文章

链表翻转的图文讲解(递归与迭代两种实现)

链表的翻转是程序员面试中出现频度最高的问题之一,常见的解决方法分为递归和迭代两种.最近在复习的时候,发现网上的资料都只告诉了怎么做,但是根本没有好好介绍两种方法的实现过程与原理.所以我觉得有必要好好的整理一篇博文,来帮忙大家一步步理解其中的实现细节.  我们知道迭代是从前往后依次处理,直到循环到链尾:而递归恰恰相反,首先一直迭代到链尾也就是递归基判断的准则,然后再逐层返回处理到开头.总结来说,链表翻转操作的顺序对于迭代来说是从链头往链尾,而对于递归是从链尾往链头.下面我会用详细的图文来剖析其中实

java实现八皇后问题(递归和循环两种方式)

循环方式: package EightQueens; public class EightQueensNotRecursive { private static final boolean AVAILABLE = true; private int squares = 8, norm = squares - 1; private int positionInRow[] = new int[squares]; private int p=-1; private boolean[] rows = n

Java连接Neo4j的两种方式

1.Neo4j数据库的两种方式 Neo4j可以以两种方式运行: Java应用程序中的嵌入式数据库 通过REST的独立服务器 不管哪一种方式,这个选择不会影响查询和使用数据库的方式. 它是由应用程序的性质(无论是独立服务器还是客户端服务器),性能,监视和数据安全性驱动的架构选择. 1.1Neo4j Server(服务器式数据库) Neo4j Server是互操作性,安全性和监控的最佳选择. 实际上,REST接口允许所有现代平台和编程语言与它进行互操作. 此外,作为独立应用程序,它比嵌入式配置更安全

[转]在计算机程序中,完成重复的任务有两种方式:递归和迭代(循环)。

在计算机程序中,完成重复的任务有两种方式:递归和迭代(循环) 递归的一个例子:从前有座山,山里有座庙,庙里一个老和尚在给小和尚讲故事,内容是“从前有座山,山里有座庙,庙里一个老和尚在给小和尚讲故事,内容是“从前有座山,山里有座庙,庙里一个老和尚在给小和尚讲故事,内容是“...... 循环的一个例子:炉子上有99锅汤,让我不小心喝了一锅,炉子上还有98锅汤;炉子上有98锅汤,让我不小心喝了一锅,炉子上还有97锅汤;炉子上有97锅汤,让我不小心喝了一锅,炉子上还有96锅汤; ...... http:

二分查找算法(递归与非递归两种方式)

首先说说二分查找法. 二分查找法是对一组有序的数字中进行查找,传递相应的数据,进行比较查找到与原数据相同的数据,查找到了返回1,失败返回对应的数组下标. 采用非递归方式完成二分查找法.java代码如下所示. /* * 非递归二分查找算法 * 参数:整型数组,需要比较的数. */ public static int binarySearch(Integer[]srcArray,int des){ //第一个位置. int low=0; //最高位置.数组长度-1,因为下标是从0开始的. int h

【剑指offer】递归循环两种方式反转链表

转载请注明出处:http://blog.csdn.net/ns_code/article/details/25737023 本文分别用非递归和递归两种方式实现了链表的反转,在九度OJ上AC. 题目描述: 输入一个链表,反转链表后,输出链表的所有元素.(hint : 请务必使用链表) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000):代表将要输入的链表的个数.输入的第二行包含n个整数t(0<=t<=1000000)

遍历获得磁盘文件的两种方式

在winform中可能有这种情况,遍历某一个文件夹得到当前文件夹中的所有文件以及子文件夹中的所有文件,以此类推,然后添加到一个TreeView控件中,或者通过控制台输出文件以及文件夹的名称.方法多种多样,下面说的是通过递归和队列的方式来进行.递归其实就是在函数调用的时候进行压栈进行的,所以可以概述为通过栈和队列来实现. 递归方式实现 private void GetAllFile (string strPath,TreeNode parentNode) { //得到当前路径下的所有文件和文件夹

数位dp初步——数位dp的两种方式

数位dp:一类统计区间[L,R]内某种符合规定的数字个数的题目.特征是R的范围会很大,O(N)范围内无法完成. 一般而言,解决这类题目有两种方式,一种是递推,另一种是记忆化搜索. 递推: 1)利用dp求出数组f[i][j](表示有i位,最高位为j的数字中符合要求的数字的个数) 2)根据给出的[L,R],利用f[]统计答案 记忆化搜索: 1 int dfs(int pos,int pre,int lim){//当前位置 前一位的数字 是否有限制 2 if(pos<=0)return 1; 3 if

PHP 实现实时通信一般有两种方式

实现实时通信一般有两种方式:socket或comet.socket是比较好的解决方案,问题在于不是所有的浏览器都兼容,服务器端实现 起来也稍微有点麻烦.相比之下,comet(基于HTTP长连接的"服务器推")实现起来更加方便,而且兼容所有的浏览器.所以这次就来说说comet的 php实现. comet也有好几种实现方式,如iframe, http long request,本文主要探讨http long request实现实时通信. 先说说http长链接是怎么回事,通俗点讲就是服务器不