八大排序算法之归并排序

01

归并排序

将待排序的数列分成若干个长度为1的子数列,然后将这些数列两两合并;得到若干个长度为2的有序数列,再将这些数列两两合并;得到若干个长度为4的有序数列,再将它们两两合并;直接合并成一个数列为止。这样就得到了我们想要的排序结果。

02

演绎过程

分解 – 将当前区间一分为二,即求分裂点 mid = (low + high)/2;

求解 – 递归地对两个子区间a[low…mid] 和 a[mid+1…high]进行归并排序。递归的终结条件是子区间长度为1。

合并 – 将已排序的两个子区间a[low…mid]和 a[mid+1…high]归并为一个有序的区间a[low…high]。

在这里插入图片描述

03

时间复杂度

时间复杂度:O(NlgN)

稳定性:稳定算法

04

代码实现

//归并排序
/**
 * @param arr 原始数组
 * @param left 左边有序序列的初始索引
 * @param right 右边有序序列的初始索引
 * @param mid 中间索引
 * @param temp 做中转的数组
 */
public static void merge(int[] arr,int left,int mid,int right,int[] temp) {

    int i = left; //初始化i左边序列的初始化索引
    int j = mid + 1;//初始化j右边序列的初始化索引
    int t = 0;//指向temp数组的当前索引

    //把左右两边的有序序列的数据按照规则填充到temp数组中,
    //直到左右两边的有序序列有一边处理完为止,
    while (i <= mid && j <= right) {

        //如果左边有序序列元素小于右边序列的元素,
        //就将左边序列的当前元素,填充到temp中
        if (arr[i] <= arr[j]) {
            temp[t] = arr[i];
            i+=1;
            t+=1;
        } else { //反之亦然
            temp[t] = arr[j];
            t+=1;
            j+=1;
        }
    }

    //把左右两边剩余的数据依次全部填充到temp中
    //剩余左边填充
    while (i <= mid ) {
        temp[t] = arr[i];
        i+=1;
        t+=1;
    }
    //剩余右边填充
    while (j <= right ) {
        temp[t] = arr[j];
        j+=1;
        t+=1;
    }

    //数组拷贝,不是每次都拷贝所有
    t = 0;
    int tempLeft = left;
    while (tempLeft <= right) {
        arr[tempLeft] = temp[t];
        t += 1;
        tempLeft += 1;
    }

}

//分+合的办法
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);

    }
}

05

总结

归并排序算法演绎过程一目了然,很容易理解,但是对于他的代码实现还是有些难度的。
主要是使用了递归思想,重点和难点也在使用递归的这点。
在归并排序中,有两次递归分别为向左和向右递归,一般来讲我们都是先向左递归,在这其中每一次递归过程中再去向右递归。每一次递归的参数不同,最后在实现排序。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炸鸡叔老白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值