归并排序
1. 算法介绍
归并排序是一种高效的 分治法(Divide and Conquer) 排序算法,核心思想:
1️⃣ 分解:将数组递归拆分为最小单位(单个元素)
2️⃣ 合并:将有序子数组合并为更大有序数组
✅ 时间复杂度:最优/平均/最坏均为 O(n log n)
✅ 稳定性:稳定排序(相同元素顺序不变)
✅ 适用场景:大数据量、链表排序、外部排序
2. 分治思想图解
初始数组: [38, 27, 43, 3, 9, 82, 10]
↓ 分解
[38, 27, 43] [3, 9, 82, 10]
↓ 分解 ↓ 分解
[38] [27, 43] [3,9] [82,10]
↓ 合并 ↓ 合并
[27, 38, 43] [3,9,10,82]
↓ 合并
[3,9,10,27,38,43,82]
3. 合并操作详解
核心步骤:合并两个有序数组
Left数组: [27, 38, 43] Right数组: [3, 9, 10, 82]
Step1: 比较左首(27) vs 右首(3) → 取较小值 3
Step2: 比较 27 vs 9 → 取 9
Step3: 比较 27 vs 10 → 取 10
Step4: 直接追加左数组:[27,38,43]
结果:[3, 9, 10, 27, 38, 43, 82]
4. C++ 代码实现
#include <vector>
using namespace std;
// 合并两个有序数组
void merge(vector<int>& arr, int left, int mid, int right) {
vector<int> temp(right - left + 1);
int i = left, j = mid + 1, k = 0;
// 合并:取较小值放入temp
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 (j <= right) temp[k++] = arr[j++];
// 拷贝回原数组
for (int idx = 0; idx < k; idx++)
arr[left + idx] = temp[idx];
}
// 归并排序主函数
void mergeSort(vector<int>& arr, int left, int right) {
if (left >= right) return; // 递归终止条件
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid); // 递归排序左半部
mergeSort(arr, mid + 1, right); // 递归排序右半部
merge(arr, left, mid, right); // 合并有序数组
}
// 调用示例
int main() {
vector<int> arr = {38, 27, 43, 3, 9, 82, 10};
mergeSort(arr, 0, arr.size() - 1);
return 0;
}
5. 关键点分析
🔹 递归深度:共 log₂n 层分解
🔹 合并成本:每层合并需 O(n) 操作
🔹 空间复杂度:O(n)(临时数组开销)
🔹 优化策略:
- 小数组用插入排序减少递归开销
- 避免频繁内存分配(全局复用 temp 数组)
6. 与快速排序对比
特性 | 归并排序 | 快速排序 |
---|---|---|
最坏时间复杂度 | O(n log n) | O(n²) |
稳定性 | ✅ 稳定 | ❌ 不稳定 |
空间复杂度 | O(n) | O(log n) 栈空间 |
适用场景 | 大数据量/外部排序 | 内存排序/随机数据 |
7. 可视化演示推荐
🔗 归并排序动画演示
(动态理解分解与合并过程)
总结:归并排序以 时间换空间,凭借稳定且可预测的性能,成为大规模数据排序的基石算法!