其他分享
首页 > 其他分享> > 归并排序

归并排序

作者:互联网

1. 归并排序——分治

# 算法原理

归并排序的思想就是分治,先递归分解数组,再合并数组。

将数组分解到最小之后,再往上一层两两合并两个有序的数组,最终递归返回的就是一个排好序的数组。

递归分解的时间复杂度是O(logn),合并数组的时间复杂度是O(n),因此归并排序的时间复杂度就是O(nlogn)

# 步骤

  1. 确定分界点
    • mid = (l + r) / 2
  2. 递归调用左右区间
    • 一层层调用到底,从最底层归并
  3. 归并排序, 合二为一

# 如何实现合二为一?

合并的基本思路就是双指针算法,比较两个数组最前面的数字,谁小就先取谁,取了后相应的指针就往后移动一位。 然后再比较,直到一个数组为空,最后把一个数组的剩余部分复制过来即可。

  1. 找两个指针中较小的一个数,把值写入res[],然后指针右移
  2. 直到其中一个序列的指针指向最后一个
  3. 把另一个序列的指针剩下的数依次写入res[]

# 代码模板

const int N = 10e5 + 10;
int temp[N];
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 i = l, j = mid + 1, k = 0;
    while(i <= mid && j <= r) {
        if( q[i] <= q[j] ) temp[k++] = q[i++];
        else temp[k++] = q[j++];
    }
    while(i <= mid) temp[k++] = q[i++];
    while(j <= r) temp[k++] = q[j++];
    for(i = l, j = 0; i <= r; i++, j++) q[i] = temp[j];
}

# 总结

归并排序没有太多复杂的边界问题,核心思想是分治,只要理解了这一点,基本上原理就弄清楚了。

在进行归并排序之前,先递归调用左右区间,可以理解为将数组二分分解。

调用到最深一层也就是区间里只有一个元素的时候,开始执行递归函数的返回,也就是执行归并的过程。

归并的过程可以如上图所示,每一层的都是把2个相邻的区间通过双指针算法排序并合并到一个区间(合并这个动作由递归返回发生),每次递归返回时区间都是有序的,最终合并回一个区间,完成排序。

需要注意的是,归并排序的时间复杂度是O(nlogn),但是中间过程需要用到一个数组来存放临时排序的结果,所以空间复杂度是O(n)。

2022.4.10

标签:归并,递归,int,数组,排序,指针
来源: https://www.cnblogs.com/Ethan-Code/p/16612583.html