排序之归并排序

前言

  小编最近学习到了归并排序,下面就与小编一起看看归并排序到底是什么?

是什么

  归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
  算法思路,将大问题化解为一个个小问题,通过解决小问题来解决大问题

代码展示

public class MergeSort {

    /**
     * 将分区的数组进行排序
     */
    public static void merge(int[] a, int start, int mid, int end) {
        int[] tmp = new int[a.length];
        System.out.println("排序区间 " + start + "~" + end);
        int i = start, j = mid + 1, k = start;
        while (i != mid + 1 && j != end + 1) {
            //将数组排序,并将排序后的结果赋值给tmp[]
            if (a[i] < a[j]) {      
                tmp[k++] = a[i++];//将左边分组赋值给tmp[]
            } else {
                tmp[k++] = a[j++];//将右边分组赋值给tmp[]
            }
        }
        while (i != mid + 1) {
            tmp[k++] = a[i++];//将剩余部分(左边分组)赋值给tmp[]数组
        }
        while (j != end + 1) {
            tmp[k++] = a[j++];//将剩余部分(右边分组)赋值给tmp[]数组
        }
        for (i = start; i <= end; i++) {
            a[i] = tmp[i];//tmp[]数组重新赋值给a[]数组
        }
        for (i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }

        System.out.println();
    }

    /**
     * 将待排数组进行分区
     */
    static void mergeSort(int[] a, int start, int end) {
        if (start < end) {
            int mid = (start + end) / 2;// 一分为二(分治法)
            mergeSort(a, start, mid);// 左边分组
            mergeSort(a, mid + 1, end);// 右边分组
            merge(a, start, mid, end);// 调用排序逻辑
        }
    }

    public static void main(String[] args) {
        int[] b = { 8,4,5,7,1,3,6,2 };
        mergeSort(b, 0, b.length - 1);
    }
}

对代码理解的不是很清楚?通过图来看,搭配着图(图是老车的)来理解,下面是分治的过程
这里写图片描述
这里是排序的的过程,也就是部分归并的过程,另一部分与此相似,就不重复展示了
这里写图片描述

  什么?什么?还是不理解?没关系,咱们把代码在原来的基础上稍微修改一下就行了

整理后的代码

public class MergeSort {

    /**
     * 将分区的数组进行排序
     */
    public static void merge(int[] a, int start, int mid, int end,int[] tmp) {

        int i = start, j = mid + 1, k = start;
        while (i != mid + 1 && j != end + 1) {
            if (a[i] < a[j]) {//将数组排序       
                tmp[k++] = a[i++];
            } else {
                tmp[k++] = a[j++];
            }
        }
        while (i != mid + 1) {
            tmp[k++] = a[i++];//将左边分组赋值给tmp[]数组
        }
        while (j != end + 1) {
            tmp[k++] = a[j++];//将右边分组赋值给tmp[]数组
        }
        for (i = start; i <= end; i++) {
            a[i] = tmp[i];//将tmp[]数组重新赋值给a[]数组
        }

        System.out.println("排序后的a数组");
        for (i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }

        System.out.println();
    }

    /**
     * 将待排数组进行分区
     */ 
    static void mergeSort(int[] a, int start, int end, int T[]) {
        if (start < end) {

            int mid = (start + end) / 2;// 一分为二(分治法)
            mergeSort(a, start, mid,T);// 左边分组
            System.out.println("左边");
            System.out.println("开始下标start是"+" "+ start+" "+"结束下标mid是"+" "+ mid);
            System.out.println("排序前a数组");
            for (int p : a) {               
                System.out.print(p + " ");
            }
            System.out.println();
            System.out.println("排序后tmp数组");
            for (int w : T) {               
                System.out.print(w + " ");
            }
            System.out.println();
            mergeSort(a, mid + 1, end,T);// 右边分组
            System.out.println("右边");
            System.out.println("开始下标mid+1是"+" "+(mid+1)+" "+"结束下标end是"+" "+ end);
            System.out.println("排序前a数组");
            for (int p : a) {               
                System.out.print(p + " ");
            }
            System.out.println();
            System.out.println("排序后tmp数组");
            for (int w : T) {           
                System.out.print(w + " ");
            }
            System.out.println();
            merge(a, start, mid, end,T);// 调用排序逻辑
        }
    }

    public static void main(String[] args) {
        int[] b = { 5, 8, 9, 6, 7, 1, 3, 4 };
        int[] T=new int[b.length];
        int c=b.length-1;
        mergeSort(b, 0, b.length - 1,T);
    }
}

输出结果

左边
开始下标start是 0 结束下标mid0
排序前a数组
8 4 5 7 1 3 6 2 
排序后tmp数组
0 0 0 0 0 0 0 0 
右边
开始下标mid+11 结束下标end1
排序前a数组
8 4 5 7 1 3 6 2 
排序后tmp数组
0 0 0 0 0 0 0 0 
排序后的a数组
4 8 5 7 1 3 6 2 
左边
开始下标start是 0 结束下标mid1
排序前a数组
4 8 5 7 1 3 6 2 
排序后tmp数组
4 8 0 0 0 0 0 0 
左边
开始下标start是 2 结束下标mid2
排序前a数组
4 8 5 7 1 3 6 2 
排序后tmp数组
4 8 0 0 0 0 0 0 
右边
开始下标mid+13 结束下标end3
排序前a数组
4 8 5 7 1 3 6 2 
排序后tmp数组
4 8 0 0 0 0 0 0 
排序后的a数组
4 8 5 7 1 3 6 2 
右边
开始下标mid+12 结束下标end3
排序前a数组
4 8 5 7 1 3 6 2 
排序后tmp数组
4 8 5 7 0 0 0 0 
排序后的a数组
4 5 7 8 1 3 6 2 
左边
开始下标start是 0 结束下标mid3
排序前a数组
4 5 7 8 1 3 6 2 
排序后tmp数组
4 5 7 8 0 0 0 0 
左边
开始下标start是 4 结束下标mid4
排序前a数组
4 5 7 8 1 3 6 2 
排序后tmp数组
4 5 7 8 0 0 0 0 
右边
开始下标mid+15 结束下标end5
排序前a数组
4 5 7 8 1 3 6 2 
排序后tmp数组
4 5 7 8 0 0 0 0 
排序后的a数组
4 5 7 8 1 3 6 2 
左边
开始下标start是 4 结束下标mid5
排序前a数组
4 5 7 8 1 3 6 2 
排序后tmp数组
4 5 7 8 1 3 0 0 
左边
开始下标start是 6 结束下标mid6
排序前a数组
4 5 7 8 1 3 6 2 
排序后tmp数组
4 5 7 8 1 3 0 0 
右边
开始下标mid+17 结束下标end7
排序前a数组
4 5 7 8 1 3 6 2 
排序后tmp数组
4 5 7 8 1 3 0 0 
排序后的a数组
4 5 7 8 1 3 2 6 
右边
开始下标mid+16 结束下标end7
排序前a数组
4 5 7 8 1 3 2 6 
排序后tmp数组
4 5 7 8 1 3 2 6 
排序后的a数组
4 5 7 8 1 2 3 6 
右边
开始下标mid+14 结束下标end7
排序前a数组
4 5 7 8 1 2 3 6 
排序后tmp数组
4 5 7 8 1 2 3 6 
排序后的a数组
1 2 3 4 5 6 7 8 

  这样对比着每一次归并来看代码,会好理解很多,而且每一次的数值变化都可以体现出来

总结

  算法是我们本次的学习目标,学习算法的根本目的不仅仅是算法,重要的是体会到这种算法的本质思想,它解决问题的方式等,好了,本次归并排序就到这里了,哪里不理解可以在博客下面留言,感谢您的阅读

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值