递归和非递归实现归并排序

1、递归实现归并排序
递归排序其实也是利用了完全二叉树的结构形式,所以时间复杂度和logN挂钩的。具体递归版的归并排序呢,看下面的代码:

    public class MS {

    public static void main(String[] args) {
         int[] s = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };  
            print(s);  
            mergeSort(s);  
            System.out.println("排序后的数组:");  
            print(s);   

    }

    public static void mergeSort(int[] data) {  
        sort(data, 0, data.length - 1);  
    }  

    public static void sort(int[] data, int left, int right) {  
        if (left >= right)  
            return;  
        // 找出中间索引  
        int center = (left + right) / 2;  
        // 对左边数组进行递归  
        sort(data, left, center);  
        // 对右边数组进行递归  
        sort(data, center + 1, right);  
        // 合并  
        merge(data, left, center, right);  
        print(data);  
    }  

    /** 
     * 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序 
     *  
     * @param data 
     *            数组对象 
     * @param left 
     *            左数组的第一个元素的索引 
     * @param center 
     *            左数组的最后一个元素的索引,center+1是右数组第一个元素的索引 
     * @param right 
     *            右数组最后一个元素的索引 
     */  
    public static void merge(int[] data, int left, int center, int right) {  
        // 临时数组  
        int[] tmpArr = new int[data.length];  
        // 右数组第一个元素索引  
        int mid = center + 1;  
        // third 记录临时数组的索引  
        int third = left;  
        // 缓存左数组第一个元素的索引  
        int tmp = left;  
        while (left <= center && mid <= right) {  
            // 从两个数组中取出最小的放入临时数组  
            if (data[left] <= data[mid]) {  
                tmpArr[third++] = data[left++];  
            } else {  
                tmpArr[third++] = data[mid++];  
            }  
        }  
        // 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)  
        while (mid <= right) {  
            tmpArr[third++] = data[mid++];  
        }  
        while (left <= center) {  
            tmpArr[third++] = data[left++];  
        }  
        // 将临时数组中的内容拷贝回原数组中  
        // (原left-right范围的内容被复制回原数组)  
        while (tmp <= right) {  
            data[tmp] = tmpArr[tmp];
            tmp++;
        }  
    }  

    public static void print(int[] data) {  
        for (int i = 0; i < data.length; i++) {  
            System.out.print(data[i] + " ");  
        }  
        System.out.println();  
    }  


}

运行结果如下:

5 3 6 2 1 9 4 8 7 
3 5 6 2 1 9 4 8 7 
3 5 6 2 1 9 4 8 7 
3 5 6 1 2 9 4 8 7 
1 2 3 5 6 9 4 8 7 
1 2 3 5 6 4 9 8 7 
1 2 3 5 6 4 9 7 8 
1 2 3 5 6 4 7 8 9 
1 2 3 4 5 6 7 8 9 
排序后的数组:
1 2 3 4 5 6 7 8 9 

2、非递归实现归并排序
由于递归的过程中要用到栈,那么这无疑会增加额外的时间和空间消耗,因此,在选择时,有限选择非递归版的归并算法。具体代码如下:

package 排序;
//非递归实现归并排序
public class NewMS {

    public static void main(String[] args) {
        int[] s = new int[] { 5, 3, 6, 2, 1, 9, 4, 8 ,7};
        print(s);  
        MergeSort2(s);
        System.out.println("排序后的数组:");

        print(s);
    }

    private static void MergeSort2(int[] s) { //该函数的作用是让数组中的元素以k进行变步长迭代
        int k=1;
        while(k<s.length){
            MergePass(s,k,s.length-1); //MergePass函数的作用是在给定步长k的情况下,实现局部合并
            k=2*k;  //k是以1、2、4、8、16为步长的,当然16步长无法实现
        }

    }

    private static void MergePass(int[] s, int k, int len) {
        int i=0;
        while(i<=len-2*k+1){//此处循环的目的是两两归并
            Merge(s,i,i+k-1,i+2*k-1);
            i=i+2*k;
            print(s);
        }
        if(i<len-k+1){//判断是否有落单的数据,如果有的话直接将其和前面相邻的一组数据进行归并
            Merge(s,i,i+k-1,len);
            print(s);
        }
    }

    private static void Merge(int[] s, int left, int m, int right) {//此部分为归并代码块
        int[] tmp=new int[s.length];
        int k=left;
        int third=left;
        int j=m+1;
        while(left<=m&&j<=right){
            if(s[left]<s[j]){
                tmp[k++]=s[left++];
            }else{
                tmp[k++]=s[j++];
            }
        }
        while(left<=m){
            tmp[k++]=s[left++];
        }
        while(j<=right){
            tmp[k++]=s[j++];
        }
        while(third<=right){
            s[third]=tmp[third];
            third++;
        }

    }

    private static void print(int[] s) {
        for(int i=0;i<s.length;i++){
            System.out.print(s[i]+" ");
        }
        System.out.println();
    }

}

运行结果如下:

5 3 6 2 1 9 4 8 7 
3 5 6 2 1 9 4 8 7 
3 5 2 6 1 9 4 8 7 
3 5 2 6 1 9 4 8 7 
3 5 2 6 1 9 4 8 7 
2 3 5 6 1 9 4 8 7 
2 3 5 6 1 4 8 9 7 
1 2 3 4 5 6 8 9 7 
1 2 3 4 5 6 7 8 9 
排序后的数组:
1 2 3 4 5 6 7 8 9 

以上就是关于归并排序的程序部分,望共享。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值