二、基础算法——归并排序

一、基本思路

1、确定分界点

在这里插入图片描述

分界点:中点-mid
mid = (l + r)/ 2; 此处取的是中点的索引,而非值本身

2、递归排序 left、right 两部分

1、保证 left 与 right 是已经排好序的两个序列
2、当递归到最小的只有一个元素的时候,进行返回
3、然后对所得到的两个元素进行归并排序,而后递归,保证左右两都是有序的

3、归并排序——合二为一

在这里插入图片描述

1、创建 temp[r - l + 1]的暂存矩阵
2、选择左、右指针中小的那个放入 temp 中,然后此指针后移一位
3、继续比较、假如一个序列到顶点,则将另一个剩下部分拼在后面

二、Java、C语言模板实现

//Java 模板实现
import java.util.Scanner;
import java.util.stream.IntStream;

public class Practice {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] arr = IntStream.range(0, n).map(i -> scanner.nextInt()).toArray();
        mergeSort(arr, 0, n-1);     			  // 可以不用数组接收,是因为进行的是引用地址值的传递,是地址的副本进行了传递
        IntStream.range(0, n).mapToObj(i -> arr[i] + " ").forEach(System.out::print);

    }

    private static int[] mergeSort(int[] arr, int left, int right){
        if (left >= right){                      // 判断是否是1个元素
            return arr;
        }

        int[] temp = new int[right - left + 1]; // 暂存数组
        int mid = left + right >> 1;            // 取中间点坐标索引
        int i = left;                           // 左边序列移动指针
        int j = mid + 1;                        // 右边序列的移动指针
        int k = 0;                              // 存储数组的指针

        mergeSort(arr, left, mid);              // 递归左边序列
        mergeSort(arr, mid + 1, right);         // 递归右边序列,此处是后面进行归并的前前提,是因为本身默认已经做好了排序了

        while(i <= mid && j <= right){          // 进行双指针变换与两序列归并
            if (arr[i] <= arr[j]){              // 选取小的进行排序
                temp[k++] = arr[i++];
            }else {
                temp[k++] = arr[j++];
            }
        }

        while (i <= mid){                       // 假如一个系列已经排完了,但是另一个有剩余,那这时候这个就是那部分剩余的合并
            temp[k++] = arr[i++];               // 注意此处是在 while 循环外面
        }
        while (j <= right){
            temp[k++] = arr[j++];
        }

        for (i = left,j = 0;i <= right; i++, j++){      // 因为是传递的地址值,那么此处实际上反传递回去,对arr进行修改
            arr[i] = temp[j];
        }
        return arr;
    }
}

```c
// C语言实现,此处是yxc实现
void merge_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int mid = l + r >> 1;
    merge_sort(q, l, mid);
    merge_sort(q, mid + 1, r);

    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r)
        if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
        else tmp[k ++ ] = q[j ++ ];

    while (i <= mid) tmp[k ++ ] = q[i ++ ];
    while (j <= r) tmp[k ++ ] = q[j ++ ];

    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}

作者:yxc
链接:https://www.acwing.com/blog/content/277/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三、注意事项

1、注意归并排序与快排的区别:归并排序是先归并,然后再进行归并操作,归并操作已经是两个排好序的数组;快排是先进行粗略分界,然后再进行递归。
2、归并排序复杂度为O(n)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

牙否

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

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

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

打赏作者

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

抵扣说明:

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

余额充值