Java数据结构与算法笔记——递归实现归并排序

合并两个有序数组

归并算法的中心是归并两个已经有序的数组。
归并两个有序数组A和B,就生成了第三个有序数组C,数组C包含数组A和B的所有数据项。
在这里插入图片描述

package recursion;

import java.lang.reflect.Array;
import java.util.Arrays;

public class RecursionTest5 {
    public static void main(String[] args) {
        int[] c = merge(new int[] {1,3,5,7},new int[] {2,4,6,8,10});
        System.out.println(Arrays.toString(c));
    }

    //循环实现归并
    public static int[] merge(int[] a, int[] b){
        int[] c = new int[a.length+b.length];//初始化合并后的数组
        //定义三个指针,分别作用于数组a,b,c
        int aNum=0;
        int bNum=0;
        int cNum=0;
        //实现归并
        while (aNum<a.length && bNum<b.length){
            //当a和b中都有剩余的元素的时候
            if(a[aNum]<b[bNum]){
                c[cNum ++] = a[aNum ++];
            }else {
                c[cNum ++] = b[bNum ++];
            }
        }
        //如果b数组先取完,a有剩余
        while (bNum == b.length && aNum<a.length){
            c[cNum ++] = a[aNum ++];
        }
        //如果a数组先取完,b有剩余
        while (aNum == a.length && bNum<b.length){
            c[cNum ++] = b[bNum ++];
        }
        return c;
    }
}

实现归并排序

归并排序的思想是把一个数组分成两半,排序每一半,再将两个有序数组合并为一个数组(如上节所示)。

那么如何为每一部分排序呢?使用递归:
将每一半都分为四分之一,对每个四分之一进行排序,然后把它们归并为一个有序的二分之一。
类似的,将每个四分之一分成两个八分之一…
依此类推,反复的分割数组,直到得到的子数组是一个数据项,一个数据项元素的数组肯定是有序的,那这就是这个递归算法的边界值。

也就是一直二分,分到只有一个元素,然后开始归并。
在这里插入图片描述

package recursion;

import java.util.Arrays;

public class RecursionTest6 {
    public static void main(String[] args) {
        int[] rs = mergeSort(new int[] {3,2,1,0,-1},0,4);
        System.out.println(Arrays.toString(rs));
    }

    //实现归并排序
    public static int[] mergeSort(int[] c, int l, int h){
        // 要排序的无序数组,排序开始的下边界,排序结束的上边界
        if(l>=h){//递归边界
            //什么都不做
        }else {
            int mid = (l+h)/2;

            //对两个子数组分别排序
            mergeSort(c,l,mid);
            mergeSort(c,mid+1,h);

            //把上面排好序的有序数组进行归并
            merge(c,l,mid,h);
        }
        return c;
    }

    //实现两个数组合并方法
    public static void merge(int[] c, int l, int mid, int h){
        //数组,下边界,中间值,上边界
        int i = l; //左边数组的第一个
        int j = mid+1; //右边数组的第一个
        int[] tmp = new int[h-l+1]; //临时数组
        int k = 0;//临时数组的索引

        //实现合并
        while (i<=mid && j<=h){
            if(c[i]<c[j]){
                tmp[k++] = c[i++];
            }else {
                tmp[k++] = c[j++];
            }
        }

        while (i<=mid && j>h){
            tmp[k++] = c[i++];
        }

        while (i>mid && j<=h){
            tmp[k++] = c[i++];
        }

        //临时数组转移到C数组中
        for(int g=0;g<tmp.length;g++){
            c[l+g] = tmp[g];
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值