算法笔记-归并排序

算法笔记-归并排序

1、归并排序是什么?

归并排序采用的是分治(divide-and-conquer)法思想。

基本思想是将一个集合递归分成两个集合,对每个集合内的数进行排序,最后再把排好序的集合再次排序

2、归并排序执行图

先来看归并排序的大致过程,这个是为了方便看,是这样的

查看源图像

可以将他的执行过程理解为一颗二叉树,每个数的子节点都是父节点对半分的集合,对每个子节点进行排序之后,再对父节点进行排序

3、Java实现归并排序的框架

以[8,4,5,7,1,3,6,2]为例子

/**
 * @author 我见青山多妩媚
 * @date Create on 2022/6/23 9:23
 */
public class Sort {
    static int count = 0;

    public static void main(String[] args) {
        int[] arr = new int[]{8, 4, 5, 7, 1, 3, 6, 2};
        mergeSort(arr, 0, arr.length - 1);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    /**分割成小区间
     * 继续分割区间,直到分割到不能分割为止,然后往下走合并两个区间
     * @param arr 数组
     * @param left 左边界
     * @param right 右边界
     */
    public static void mergeSort(int[] arr, int left, int right) {
        //先判断分割的区间是否合法
        if (left >= right) return;
        int mid = (left + right) / 2;
        //分割左区间
        mergeSort(arr, left, mid);
        //分割右区间
        mergeSort(arr, mid+1, right);
        //对两个区间排序,合并两个区间
        merge(arr, left, mid, right);
    }

    /**
     * 对每个小区间进行排序,合并两个区间
     * @param arr arr
     * @param left  左边界,左区间[left,mid]
     * @param mid  左右区间分割界限
     * @param right 右边界,右区间[mid+1,right]
     */
    public static void merge(int[] arr, int left, int mid, int right) {
        //临时数组,用于存放排序过后的数,长度为左右区间总长度length=right-left+1
        int[] temp = new int[right - left + 1];
        //i为左边区间开始下标[left,mid],j为右边区间开始下标[mid+1,right],k为临时数组下标
        int i = left, j = mid + 1, k = 0;
        //当length=2时,判断的是两个相邻的数大小,当length>2时,判断的是两个已经排好序的区间大小,可以自己debug看一下具体过程,挺有意思的
        //每次判断都是把小的加到临时数组内
        while (i <= mid && j <= right) {
            if (arr[i] < arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }

        //如果其中一个数还没区间分割点,那么说明上一个while循环已经把满足的全部加到临时数组了,那么把没有遍历完的一个区间按顺序加入临时数组即可(因为是排好序的)
        //左区间加入
        while (i <= mid) {
            temp[k++] = arr[i++];
        }

        //右区间加入
        while (j <= right) {
            temp[k++] = arr[j++];
        }

        //将排好序的值依次重新赋给原数组,left+t为该数组本次开始遍历下标
        for (int t = 0; t < k; t++) {
            arr[left + t] = temp[t];
        }

    }
}

运行结果:

1 2 3 4 5 6 7 8 
4、时间复杂度分析

查看源图像

**附:**关于归并的一个算法
力扣-数组中的逆序对

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值