教您搞懂归并排序

归并排序的算法原理:该算法采用经典的分治策略,分是指将问题分成许多小的问题,然后递归求解,而治则是将分的阶段得到的各答案"修补"在起,即分而治之。

归并排序图解:图片如有侵权请联系本人

合并相邻子序列:

 归并排序代码框架:

public class MergeSort {

    /**
     * 分治算法:分阶段,将数组每个元素分开
     * @param arr   待排序数组
     * @param left  待排序数组最左边索引
     * @param mid   待排序数组中间索引
     * @param right 待排序数组最右边索引
     * @param temp  临时数组
     */
    public static void Merge(int[]arr,int left,int mid,int right,int[]temp){
        ...
    }

    public static void MergeSort(int[] arr,int left,int right,int[]temp){
        ...
    }

    public static void main(String[] args) {
        调用MergeSort
    }

}

直接讲解代码:

待排序的数组:arr = {8,4,5,7,1,3,6,2}临时数组:temp = { }
归并排序的两个函数MergeSort(arr,left,right,temp)Merge(arr,left,mid,right,temp)
第一次:(进入主函数)
left = 0right = arr.length-1 = 7mid = (left+right)/2 = 3
递归退出条件 left<right,即0<7开始执行左递归函数
第二次:(进入左递归1)左递归函数:MergeSort( arr , left , mid , temp ),right = mid
left = 0right = mid = 3mid = (left+right)/2 = 1
递归退出条件:left<right,即0<3左递归:MergeSort(arr,0,3,temp)
第三次:(进入左递归2)
left = 0right = mid = 1mid = (left+right)/2 = 0
递归退出条件:left<right,即0<1左递归:MergeSort(arr,0,1,temp)
第四次:(退出左递归,执行下一条函数语句)
left = 0right = mid = 0mid = (left+right)/2 = 0
递归退出条件:left<right,即0<0不成立开始执行右递归
第五次:(进入右递归1)右递归函数:MergeSort( arr, mid+1 , right , temp ),left = mid+1
mid = (left+right)/2 = 3 , 第1次中的left和rightleft = mid+1 = 4right = arr.length-1 = 7
递归退出条件:left<right,即4<7右递归:MergeSort(arr,4,7,temp)
第六次:(进入右递归2)
mid = (left+right)/2 = 5left = mid+1 = 6right = arr.length-1 = 7
递归退出条件:left<right,即6<7右递归:MergeSort(arr,6,7,temp)
第七次(退出右递归,执行下一条函数语句)
mid = (left+right)/2 = 6left = mid+1 = 7right = arr.length-1 = 7
递归退出条件:left<right,即7<7不成立退出右递归
第八次(开始执行Merge操作)Merge(arr,left,mid,right,temp)

Java栈内存演示:函数执行出栈操作,从上往下执行;

第一阶段:左递归阶段

 

第二阶段:右递归阶段

第三阶段:Merge阶段

import java.util.Arrays;

public class MergeSort {

    /**
     * 分治算法:分阶段,将数组每个元素分开
     * @param arr   待排序数组
     * @param left  待排序数组最左边索引
     * @param mid   待排序数组中间索引
     * @param right 待排序数组最右边索引
     * @param temp  临时数组
     */
    public static void Merge(int[]arr,int left,int mid,int right,int[]temp){
        // 0.初始化操作
        int i=left; // 左边有序序列索引
        int j=mid+1; // 右边有序序列索引
        int t=0; // 临时数组的当前索引

        // 1.先把左右两个数组按照有序规则填充到temp数组,直到两边的有序序列有一边处理完为止
        while (i<=mid&&j<=right){
            // 处理左边
            if (arr[i]<=arr[j]){
                temp[t]=arr[i];
                t++;
                i++;
            }else {// 处理右边
                temp[t]=arr[j];
                j++;
                t++;
            }
        }
        // 2.把有剩余的数据一边依次全部填充到temp
        // 2.1左边数据有剩余
        while (i<=mid){
            temp[t]=arr[i];
            t++;
            i++;
        }
        // 2.2右边数据有剩余
        while (j<=right){
            temp[t]=arr[j];
            t++;
            j++;
        }

        // 3.将temp数组的元素拷贝到arr,注意不是每次拷贝所有的arr数组元素
        t = 0; //让t指向temp首元素
        int tempLeft = left;
        while (tempLeft<=right){
            arr[tempLeft] = temp[t];
            t++;
            tempLeft++;
        }

    }

    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);
        }
    }

    public static void main(String[] args) {
        int[] arr = {8,4,5,7,1,3,6,2};
        int[] temp = new int[arr.length];
        int left = 0;
        int right = arr.length-1;
        int mid = (left+right)/2;
        System.out.println("原数组:"+Arrays.toString(arr));
        MergeSort(arr,left,right,temp);
        System.out.println("归并排序:"+Arrays.toString(arr));
    }

}

运行结果:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值