归并排序的实现

归并排序的学习

思想

由大到小

归并算法是分治算法的典型问题

1.需要我们将一个数组拆成许多的有序子序列(相当于只有一个元素)

2.然后将这些有序子序列进行两两排序组合成新的子序列,然后将这些子序列进行进一步排列组合(组合的时候需要创建一个和数组长度相同的备用数组
3.组合时的思路就是:两个子序列的第一个数相比较,把小的放到第一位,然后拿另一个数B与其他数作比较如果这个数B比另一个数大,那么把另一个数放进去,如果这个数B比另一个数小,那么把B放进去,拿另一个数当作B再做比较,当一个子序列的数全部放进去后,直接把剩余的都放到后面。

4.最后将合并的序列从创建的数组复制到原数组中

图示

下面的图表示归并排序的过程
在这里插入图片描述
上半部分表示分的阶段l,m,r分别表示序列的左下标,中间下标和右下标。
下半部分表示和的阶段,tempLeft和tempRight表示要合并的两部分的起始下标。

代码部分

代码主要分为合并算法以及递归算法(分与和的实现)
ps:如果递归的过程不是很了解的话可以参考递归算法的一些理解
ps:通过对arr[]数组在不同位置的遍历分析可以知道分与和是同时进行的

public class Merge {
    public static void main(String[] args) {
        int[] arr = {5, 2, 9, 7, 6, 4, 8, 3};
        int[] temp = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 由大到小
     * 归并算法是分治算法的典型问题
     * 需要我们将一个数组拆成许多的有序子序列(相当于只有一个元素)
     * 然后将这些有序子序列进行两两排序组合成新的子序列,然后将这些子序列进行进一步排列组合
     * 组合时的思路就是 两个子序列的第一数相比较,把大的放到第一位,然后拿另一个数与其他数作比较
     * 如果大于这个数那么放进去,如果小于这个数那么把这个数放进去,拿下一个数再做比较
     * 当一个子序列的数全部放进去后,直接把剩余的都放到后面
     */
    //合并算法
    public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        int tempLeft = left;//左边那一部分的起始下标
        int tempRight = mid + 1;//右边那一部分的起始下标
        int t = 0;//temp数组的起始下标
        //1.将两部分各取一个进行比较大小,然后将小的数放入temp,直到有一边取完
        while (tempLeft <= mid && tempRight <= right) {
            if (arr[tempLeft] <= arr[tempRight]) {
                temp[t] = arr[tempLeft];
                tempLeft++;
                t++;
            } else {
                temp[t] = arr[tempRight];
                tempRight++;
                t++;
            }
        }
        //2.当有一边取取完后,将另一边剩余的数放入temp中
        while (tempLeft <= mid) {
            temp[t] = arr[tempLeft];
            tempLeft++;
            t++;
        }
        while (tempRight <= right) {
            temp[t] = arr[tempRight];
            tempRight++;
            t++;
        }
        //3.将合并好的序列从temp数组复制到arr数组
        int l = left;
        t = 0;
        while (l <= right) {
            arr[l] = temp[t];
            t++;
            l++;
        }
    }

    //递归算法
    //分和合
    public static void mergeSort(int[] arr, int left, int right, int[] temp) {
        if (left < right) {
            int mid = (left+right)/2;
            mergeSort(arr,left,mid,temp);//左边进行分解
            mergeSort(arr,mid+1,right,temp);//右边进行分解
            merge(arr,left,mid,right,temp);//合并
        }
    }
}

ps:在递归算法中加上

			foreachArray(temp);
            foreachArray(arr);
            printLine();

可以对每一次递归后的temp数组和arr数组进行显示

更新后的代码:

public static void mergeSort(int[] arr, int left, int right, int[] temp) {
        if (left < right) {
            int mid = (left+right)/2;
            mergeSort(arr,left,mid,temp);//左边进行分解
            mergeSort(arr,mid+1,right,temp);//右边进行分解
            merge(arr,left,mid,right,temp);//合并
            foreachArray(temp);
            foreachArray(arr);
            printLine();
        }
    }

foreachArray

public static void foreachArray(int[] arr){
        System.out.println(Arrays.toString(arr));
    }

printLine

public static void printLine(){
        System.out.println("----------华丽的分割线-----------");
    }

运行结果

[2, 5, 0, 0, 0, 0, 0, 0]
[2, 5, 9, 7, 6, 4, 8, 3]
----------华丽的分割线-----------
[7, 9, 0, 0, 0, 0, 0, 0]
[2, 5, 7, 9, 6, 4, 8, 3]
----------华丽的分割线-----------
[2, 5, 7, 9, 0, 0, 0, 0]
[2, 5, 7, 9, 6, 4, 8, 3]
----------华丽的分割线-----------
[4, 6, 7, 9, 0, 0, 0, 0]
[2, 5, 7, 9, 4, 6, 8, 3]
----------华丽的分割线-----------
[3, 8, 7, 9, 0, 0, 0, 0]
[2, 5, 7, 9, 4, 6, 3, 8]
----------华丽的分割线-----------
[3, 4, 6, 8, 0, 0, 0, 0]
[2, 5, 7, 9, 3, 4, 6, 8]
----------华丽的分割线-----------
[2, 3, 4, 5, 6, 7, 8, 9]
[2, 3, 4, 5, 6, 7, 8, 9]
----------华丽的分割线-----------
[2, 3, 4, 5, 6, 7, 8, 9]

从中可以看出分和合是同时进行的

小结

本人也是刚开始接触排序算法,通过别人的博客,视频,以及自己的理解对归并算法进行了一些总结。归并算法对于递归的一些运用也是理解的不够深入。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值