数据结构与算法之归并排序

1. 归并排序原理

归并排序的思想是分而治之。什么意思呢?就是把一件大的问题拆分成很多小问题来解决,先解决一个个小问题,最后大问题就随之解决了。
image-20210331175223286

如上图,假设需要对上面的数组进行排序。分而治之看待这个问题:将数组分成两半,那么整个问题就演变成左边需要排好序,右边也需要排好序,最后把左边排好序的数组和右边排好序的数组进行合并。

左边的数组又如何排序呢?同样将数组对半分成【1,4】和【6,7,10】,排好左边和右边的数组再合并。

依上写出归并排序的伪步骤:

  1. 将数组分成左右两半
  2. 左边用归并排序排好序
  3. 右边用归并排序排好序
  4. 左右两边已经有序的数组合并

总结出来发现,不管怎样,都需要一个合并两个有序数组的算法。普通的想法,就是把第二个数组的数和第一个数组的数进行比较然后移动位置。这样做下去会发现时间复杂度太高了,每次插入一个数都需要把其他的数往后移动,相当于做了一遍插入排序。

考虑以空间换时间的方式,new一个长度相同的数组,将比较后的结果移动到这个新建的数组中,这样移动的次数就是O(n)了。

2.合并代码实现

      public static void merge(int[] arrays, int left, int mid, int right) {
        //模板数组,用来存放排好的数字
        int[] temp = new int[right - left+1];
        int i = left;
        int j = mid+1;
        int k = 0;
        while (i <= mid && j <= right) {
//            if (arrays[i] <= arrays[j]) {
//                temp[k] = arrays[i];
//                i++;
//                k++;
//            } else {
//                temp[k] = arrays[j];
//                j++;
//                k++;
//            }
            temp[k++] = arrays[i] <= arrays[j] ? arrays[i++] : arrays[j++];
        }
        while (i <= mid) {
            temp[k++] = arrays[i++];
        }

        while (j <= right) {
            temp[k++] = arrays[j++];
        }

        //将temp数组赋值给arrays数组
        for (int l = 0; l < temp.length; l++) {
            arrays[left + l] = temp[l];
        }
    }

3. 递归的归并排序算法实现

  public static void mergeSort(int[] arrays, int left, int right) {
        //对半拆分数组 递归算法不太好理解,凡是递归算法都会有一个条件跳出递归,不然就会一直递归下去,造成栈溢出,这里left==right的时候表示只有一个元素的数组的时候
        if (left == right) return;
        int mid = (left + right) / 2;
        mergeSort(arrays, left, mid);
        mergeSort(arrays, mid+1, right);
        merge(arrays, left, mid, right);
    }

4. 归并排序的时间复杂度和空间复杂度

时间复杂度:归并排序中,每一层处理的数据量为 O(n) 级别,同时有 logn 层,时间复杂度便是 O(nlogn)

空间复杂度:我们在写代码时,完全可以用空间来换取时间,比如字典树,哈希等都是这个原理。算法在运行过程中临时占用的存储空间随算法的不同而异,有的算法只需要占用少量的临时工作单元,而且不随问题规模的大小而改变,我们称这种算法的空间复杂度为O(1),注意这并不是说仅仅定义一个临时变量;有的算法需要占用的临时工作单元数与解决问题的规模n有关,它随着n的增大而增大,当n较大时,将占用较多的存储单元,比如归并排序,每次执行的时候都会用到一个辅助数组,这个辅助数组的空间就跟数组的长度n有关。所以归并排序的空间复杂度为O(n)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小菜的OnePiece

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

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

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

打赏作者

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

抵扣说明:

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

余额充值