归并排序算法详解(递归处理)


基本思想

从名字可以看到,归并排序算法,何为归并?就是把小的部分归并成大的部分。因此归并排序算法其实采用了分治的策略,也就是把一个问题分成若干个小的方便处理的问题,最后再把这些小问题得到的答案合并起来,得到最终的答案。
我们常见的归并排序算法其实是二分归并排序,也就是我们把一个数组序列分为左右两部分(每一部分会继续划分左右两部分),然后对这两部分分别进行排序,左右排序完成后,再将这两部分合并起来,简化排序的过程。
具体的细节我建议大家去看代码中的逻辑,跟着代码走一遍,会理解的更加清楚,话不多说上代码

一、代码示例


import java.util.Arrays;
import java.util.Random;

/**
 * 归并排序算法
 */
public class MergeSort {
    public static void mergeSort(int[] arr){
        if(arr ==null ||arr.length<2){
            return ;
        }
        process(arr,0,arr.length-1);
    }

    public static void process(int[] arr,int left,int right){
        int mid = left+((right - left) >> 1);
        if (left == right){
            return;
        }
        process(arr,left,mid);
        process(arr,mid+1,right);
        Merge(arr,left,mid,right);
    }

    public static void Merge(int[] arr, int left, int mid, int right) {
        int p1 = left;
        int p2 = mid+1;
        int []help = new int[right - left +1];
        int i = 0;
        //对比左右两部分的值,进行有序排列
        while(p1<=mid && p2<=right){
            help[i++] = arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
        }
        while (p1<=mid){
            help[i++] = arr[p1++];
        }
        while (p2<=right){
            help[i++] = arr[p2++];
        }
        for (int j = 0;j<help.length;j++) {
            arr[left+j] = help[j];
        }
    }
    /**
     * 随机生成数组序列
     * @param maxSize 序列最大长度
     * @param maxValue 序列最大值
     * @return
     */
    public static int[] generateRandomArray(int maxSize,int maxValue){
        Random random = new Random();
        int[] arr = new int[(int) random.nextInt(maxSize+1)];
        for(int i = 0;i<arr.length;i++){
            arr[i] = random.nextInt(maxValue + 1);
        }
        return arr;
    }

    public static void main(String[] args) {
        int[] arr = generateRandomArray(10,10);
        System.out.println(Arrays.toString(arr));
        mergeSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

细节
上面代码中求中值时没有用int mid = (left + right)/ 2,是因为当数值很大时,left + right的值会溢出,这其实是一个小bug,这里我们采用减法的形式,不会造成溢出的情况,此外,使用>>这种二进制运算的形式也可以加快代码的运行速度。

二、复杂度分析

因为这里我们采用了递归的形式进行计算,并且它的复杂度符合master公式:
master公式
在上述公式中,a是递归过程中的子递归的个数,N/b是每一部分子递归的数据规模,d是除了子递归外的剩余操作步数。
很明显,在二分归并排序算法中,a= 2,b=2,d=1,因此它的时间复杂度O(N * log(n))
空间复杂度:在Merge函数中,我们创建了一个临时数组,因此空间复杂度为O(n)

尾注

留下笔记,只为方便回忆,如有侵权,还请联系,如有错误,恳请纠正。陆续更新,还请关注。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值