一、算法思想
归并排序的核心思想是 分治法(Divide and Conquer):
分解:将待排序数组递归地分成两半
解决:对子数组进行排序
合并:将两个有序子数组合并成一个有序数组
二、算法特性
时间复杂度:O(nlogn)(最优/平均/最差情况)
空间复杂度:O(n)(需要额外存储空间)
稳定性:稳定(相同元素相对位置不变)
三、C语言实现
#include <stdio.h>
#include <stdlib.h>
// 合并两个有序数组
void merge(int arr[], int left, int mid, int right) {
int n1 = mid - left + 1; // 左子数组长度
int n2 = right - mid; // 右子数组长度
// 创建临时数组
int *L = (int*)malloc(n1 * sizeof(int));
int *R = (int*)malloc(n2 * sizeof(int));
// 拷贝数据到临时数组
for (int i = 0; i < n1; i++)
L[i] = arr[left + i];
for (int j = 0; j < n2; j++)
R[j] = arr[mid + 1 + j];
// 合并临时数组回原数组
int i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
// 拷贝剩余元素
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
free(L);
free(R);
}
// 归并排序主函数
void mergeSort(int arr[], int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2; // 防止溢出
// 递归排序左右子数组
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
// 合并已排序的子数组
merge(arr, left, mid, right);
}
}
// 打印数组
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int main() {
int arr[] = {12, 11, 13, 5, 6, 7};
int arr_size = sizeof(arr) / sizeof(arr[0]);
printf("原始数组: \n");
printArray(arr, arr_size);
mergeSort(arr, 0, arr_size - 1);
printf("\n排序后数组: \n");
printArray(arr, arr_size);
return 0;
}
四、关键代码解析
merge函数:
创建临时数组存储左右子数组
使用双指针法合并两个有序数组
保证排序稳定性(
<=
判断)
mergeSort函数:
递归终止条件:
left >= right
计算中点:
mid = left + (right - left)/2
(避免整数溢出)先递归排序,后合并结果
五、执行过程示例
原始数组: [12, 11, 13, 5, 6, 7] 分解过程: [12, 11, 13] 和 [5, 6, 7] → [12] [11,13] 和 [5] [6,7] → 排序合并:[11,13] → [11,12,13] → 排序合并:[5,6,7] → 最终合并:[5,6,7,11,12,13]
六、性能分析
情况 | 时间复杂度 | 空间复杂度 |
---|---|---|
最优 | O(nlogn) | O(n) |
平均 | O(nlogn) | O(n) |
最差 | O(nlogn) | O(n) |
辅助空间 | O(n) |
注:虽然归并排序需要额外空间,但其稳定性和可预测的性能使其成为:
大数据量排序的优选
外部排序的基础(如海量数据排序)
链表排序的最佳选择
七、优化方向
小数组优化:当子数组小于阈值时改用插入排序
免复制合并:交替使用原始数组和辅助数组
迭代法实现:消除递归调用栈
八、总结
归并排序凭借其 稳定 的时间复杂度和 稳定排序 的特性,在以下场景表现优异:
需要稳定排序的场合(如数据库排序)
链表排序(仅需修改指针,空间复杂度降为O(1))
大数据量排序(优于O(n²)算法)