图解归并排序

归并排序的流程如下

第一步:对数列每次都进行切分,直到不能再切分
这里写图片描述

每次都对数列进行切分分组,直到每组的元素都只有一个,学过递归的话很容易想到这种重复性的动作用递归很容易实现。对于8个数的数列,切分三次直到第四层就不能再切分了。

第二步:进行归并

对于上述的数列,当每组的元素都是一个,也就是说每组的都是有序的了,递归返回,返回到倒数第二层。此时可对每组元素进行归并

这里写图片描述

再进行归并

这里写图片描述

可以看到归并将每组的数排成有序的了,最后我们将最后两组数再进行归并即可。

这里写图片描述

此时,数列有序,归并结束

编程思路

对于每次把数列按半切分分组,对分好的组进行归并这个流程可以用递归实现:

//归并过程
    public static void merge(int arr[],int l,int mid,int r){
        //归并排序辅助数组
        int T[] = new int[r-l+1];
        //T[0]到T[r-l]保存arr[l]到arr[r]的值
        for(int i = l; i <= r; i++){
            T[i-l] = arr[i];
        }
        //使用i指向分组1的第一个数的位置,j指向分组2的第一个数的索引
        int i = l,j = mid+1;
        //需要归并的数组位置是[l,r]
        for(int k = l ; k <= r; k++){

            if(i > mid){    //归并后,分组2还有元素,依次覆盖到原数组对应处
                arr[k] = T[j-l];
                j++;
            }else if(j > r){    //归并后,分组1还有元素,依次覆盖到原数组对应处
                arr[k] = T[i-l];
                i++;
            }else if(T[i-l] < T[j-l]){ //将分组中小的数覆盖到原数组对应处
                arr[k] = T[i-l];
                i++;
            }else if(T[i-l] >= T[j-l]){
                arr[k] = T[j-l];
                j++;
            }
        }

    }

T[]是辅助数组,用来存放两个需要进行归并的分组。在归并时,每次将两组中的最小的那个数依次放到原数组。

这个过程如下所示:
这里写图片描述

优化

public static void merge_sort(int arr[],int l,int r){
        if(l >= r)
            return;
        /**对于数不是很多的情况下,可以使用插入排序代替归并来提高效率
         * if(r - l <= 10){
         *      插入排序;
         *      return;
         * }
        */
        int mid = (l+r) / 2;
        merge_sort(arr,l,mid);
        merge_sort(arr,mid+1,r);
        //优化,归并时左边的最后一个数已经是小于右边第一个数时,可以不用归并了
        if(arr[mid] > arr[mid+1]){
            merge(arr,l,mid,r);
        }
    }
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值