归并排序(Merge Sort)原理详解
归并排序是一种基于分治法(Divide and Conquer)的高效排序算法,由冯·诺依曼于1945年提出。它的核心思想是将大问题分解为小问题,解决小问题后再合并结果。
核心原理
1. 分治策略(Divide and Conquer)
- 分(Divide):将无序数组递归地拆分成更小的子数组,直到每个子数组只有一个元素(此时可视为已排序)
- 治(Conquer):将相邻的有序子数组合并成更大的有序数组
- 合(Combine):重复合并过程,直到整个数组有序
2. 合并过程(关键步骤)
合并两个已排序的子数组 [left…mid] 和 [mid+1…right]:
- 创建临时数组存放合并结果
- 使用两个指针分别指向两个子数组的起始位置
- 比较指针所指元素,将较小的元素放入临时数组
- 移动指针,重复比较过程
- 将剩余元素直接复制到临时数组末尾
- 将临时数组复制回原数组对应位置
算法步骤详解
-
递归分解:
- 计算中点 mid = (left + right) / 2
- 递归排序左半部分:mergeSort(arr, left, mid)
- 递归排序右半部分:mergeSort(arr, mid+1, right)
-
合并有序子数组:
- 创建临时数组 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]
优势与应用场景
优势:
- 稳定时间复杂度:始终保证 O(n log n) 的性能
- 稳定排序:保持相等元素的原始顺序
- 适合大数据集:性能不受输入数据分布影响
- 适合外部排序:可处理内存放不下的大文件
典型应用:
- 大型数据库排序
- 外部排序(如文件排序)
- 需要稳定排序的场景
- 链表排序(归并排序是链表排序的最佳选择)
- 逆序对计算(利用合并过程的特性)
与快速排序对比
| 特点 | 归并排序 | 快速排序 |
|---|---|---|
| 时间复杂度 | 始终 O(n log n) | 平均 O(n log n),最差 O(n²) |
| 空间复杂度 | O(n) | O(log n)(递归栈空间) |
| 稳定性 | 稳定 | 不稳定 |
| 额外空间 | 需要 | 可原地排序 |
| 数据敏感度 | 不受输入数据影响 | 受数据分布影响 |
| 缓存友好性 | 较差(跳跃访问) | 较好(局部性原理) |
归并排序凭借其稳定的 O(n log n) 时间复杂度和稳定性,成为大规模数据排序的重要工具,尤其在需要稳定排序或外部排序的场景中具有不可替代的优势。
归并排序:分治策略实现高效排序
38

被折叠的 条评论
为什么被折叠?



