归并排序:高效分治的艺术

归并排序:分治策略实现高效排序

归并排序(Merge Sort)原理详解

归并排序是一种基于分治法(Divide and Conquer)的高效排序算法,由冯·诺依曼于1945年提出。它的核心思想是将大问题分解为小问题,解决小问题后再合并结果。

核心原理

1. 分治策略(Divide and Conquer)

  • 分(Divide):将无序数组递归地拆分成更小的子数组,直到每个子数组只有一个元素(此时可视为已排序)
  • 治(Conquer):将相邻的有序子数组合并成更大的有序数组
  • 合(Combine):重复合并过程,直到整个数组有序

2. 合并过程(关键步骤)

合并两个已排序的子数组 [left…mid] 和 [mid+1…right]:

  1. 创建临时数组存放合并结果
  2. 使用两个指针分别指向两个子数组的起始位置
  3. 比较指针所指元素,将较小的元素放入临时数组
  4. 移动指针,重复比较过程
  5. 将剩余元素直接复制到临时数组末尾
  6. 将临时数组复制回原数组对应位置

算法步骤详解

  1. 递归分解

    • 计算中点 mid = (left + right) / 2
    • 递归排序左半部分:mergeSort(arr, left, mid)
    • 递归排序右半部分:mergeSort(arr, mid+1, right)
  2. 合并有序子数组

    • 创建临时数组 temp[right-left+1]
    • 初始化指针:i=left(左数组起点),j=mid+1(右数组起点),k=0(临时数组起点)
    • 比较 arr[i] 和 arr[j],将较小值放入 temp[k]
    • 递增较小值所在数组的指针和 k
    • 重复直到某个子数组全部处理完
    • 将剩余元素复制到 temp
    • 将 temp 复制回 arr[left…right]

动态示例

原始数组:[38, 27, 43, 3, 9, 82, 10]

分解过程:
[38, 27, 43, 3, 9, 82, 10]
→ [38, 27, 43] 和 [3, 9, 82, 10]
→ [38] [27, 43] | [3,9] [82,10]
→ [38] [27] [43] | [3] [9] [82] [10]

合并过程:
第一层合并:
[27, 38] ← 合并 [27] 和 [38](排序后)
[3, 9] ← 合并 [3] 和 [9]
[10, 82] ← 合并 [10] 和 [82]

第二层合并:
[27, 38, 43] ← 合并 [27,38] 和 [43]
[3, 9, 10, 82] ← 合并 [3,9] 和 [10,82]

最终合并:
[3, 9, 10, 27, 38, 43, 82] ← 合并两个有序数组

算法特性

特性说明
时间复杂度最优/最差/平均均为 O(n log n)
空间复杂度O(n)(需要与原始数组等大的临时空间)
稳定性稳定排序(相同元素相对位置不变)
是否原地排序否(需要额外空间)
适用场景大数据量排序、外部排序、链表排序

伪代码实现

function mergeSort(arr, left, right):
    if left < right:
        mid = (left + right) / 2
        mergeSort(arr, left, mid)     // 排序左半部
        mergeSort(arr, mid+1, right)  // 排序右半部
        merge(arr, left, mid, right)  // 合并两个有序数组

function merge(arr, left, mid, right):
    temp = new array of size (right-left+1)
    i = left, j = mid+1, k = 0
    
    // 比较并合并
    while i <= mid and j <= right:
        if arr[i] <= arr[j]:
            temp[k++] = arr[i++]
        else:
            temp[k++] = arr[j++]
    
    // 复制剩余元素
    while i <= mid: temp[k++] = arr[i++]
    while j <= right: temp[k++] = arr[j++]
    
    // 复制回原数组
    for p = 0 to k-1:
        arr[left+p] = temp[p]

优势与应用场景

优势:

  1. 稳定时间复杂度:始终保证 O(n log n) 的性能
  2. 稳定排序:保持相等元素的原始顺序
  3. 适合大数据集:性能不受输入数据分布影响
  4. 适合外部排序:可处理内存放不下的大文件

典型应用:

  • 大型数据库排序
  • 外部排序(如文件排序)
  • 需要稳定排序的场景
  • 链表排序(归并排序是链表排序的最佳选择)
  • 逆序对计算(利用合并过程的特性)

与快速排序对比

特点归并排序快速排序
时间复杂度始终 O(n log n)平均 O(n log n),最差 O(n²)
空间复杂度O(n)O(log n)(递归栈空间)
稳定性稳定不稳定
额外空间需要可原地排序
数据敏感度不受输入数据影响受数据分布影响
缓存友好性较差(跳跃访问)较好(局部性原理)

归并排序凭借其稳定的 O(n log n) 时间复杂度和稳定性,成为大规模数据排序的重要工具,尤其在需要稳定排序或外部排序的场景中具有不可替代的优势。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

代码的余温

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

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

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

打赏作者

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

抵扣说明:

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

余额充值