排序(二)归并排序

参考: https://www.bilibili.com/video/BV1Ax411U7Xx
2路归并排序:分治+合并

分治:对于n个数,我们认为每个单独的数是有序的,对于两个有序的子序列,两两归并;得到[n/2]个长度为2的有序子序列,然后再两两归并;如此重复,直到得到一个长度为n的有序序列。

合并:对于一个大序列中的两个有序子序列,按照从小到大的顺序合并(归并排序)。先拆成两个小序列,再从小到大逐一合并到原数组。

算法实现:

	// 归并
    public static void merge(int arr[], int l, int m, int r){
        // 先拆成两个有序子序列
        int leftSize = m - l;
        int rightSize = r - m + 1;
        int left[] = new int[leftSize];
        int right[] = new int[rightSize];
        for(int i=0;i<leftSize;i++){
            left[i] = arr[l + i];
        }
        for(int i=0;i<rightSize;i++){
            right[i] = arr[m + i];
        }
        // 归并排序
        // 三个指针:i指向left数组的最小元素,j指向right数组的最小元素,k指向arr数组的最下方元素。
        // 两个过程:比较填充阶段、某一个数组填充完毕后直接填充另一数组阶段
        int i = 0, j = 0, k = l;
        while(i < leftSize && j < rightSize){
            if(left[i] < right[j]){
                arr[k] = left[i];
                k++;
                i++;
            }else{
                arr[k] = right[j];
                k++;
                j++;
            }
        }
        if(i != leftSize){
            while(i < leftSize){
                arr[k] = left[i];
                k++;
                i++;
            }
        }else{
            while(j < rightSize){
                arr[k] = right[j];
                k++;
                j++;
            }
        }
    }
    
    // 分治
    public static void mergeSort(int arr[], int l, int r){
        //递归出口,单个元素一定是有序序列。
        if(l == r) return;
        //递归过程:拆分后归并
        //m要和归并时的m指向(归并时m指向拆分后的右边第一个元素)保持一致
        int m = (l + r + 1) / 2;
        mergeSort(arr, l , m-1);
        mergeSort(arr, m , r);
        merge(arr, l , m , r);
    }

    public static void main(String[] args){
        int[] arr = {4,7,9,1,3,3,5,2};
        mergeSort(arr, 0, arr.length-1);
        for(int i:arr){
            System.out.println(i);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值