1. 避免重复内存分配:每次合并时动态分配临时数组会带来性能损耗,可以预先分配一个全局临时数组,减少内存分配次数。
2. 小数组使用插入排序:当子数组规模较小时(如长度 ≤ 15),插入排序效率更高,可减少递归调用开销。
3. 非递归实现(自底向上):用循环代替递归,避免栈溢出风险,适合超大规模数据。
4. 提前检查有序性:合并前检查左右子数组是否已有序,避免不必要的合并操作。
优化后代码:
#include <stdio.h>
#include <stdlib.h>
// 插入排序(用于小规模数据)
void insertionSort(int arr[], int left, int right) {
for (int i = left + 1; i <= right; i++) {
int key = arr[i];
int j = i - 1;
while (j >= left && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
// 合并函数(使用预分配临时数组)
void merge(int arr[], int temp[], int left, int mid, int right) {
int i = left, j = mid + 1, k = left;
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 (k = left; k <= right; k++) {
arr[k] = temp[k];
}
}
// 归并排序主函数(递归+优化)
void mergeSort(int arr[], int temp[], int left, int right) {
const int INSERTION_THRESHOLD = 15; // 插入排序阈值
if (right - left <= INSERTION_THRESHOLD) {
insertionSort(arr, left, right);
return;
}
int mid = left + (right - left) / 2;
mergeSort(arr, temp, left, mid);
mergeSort(arr, temp, mid + 1, right);
// 检查是否已有序
if (arr[mid] <= arr[mid + 1]) return;
merge(arr, temp, left, mid, right);
}
// 封装的归并排序入口函数
void optimizedMergeSort(int arr[], int n) {
int* temp = (int*)malloc(n * sizeof(int)); // 预分配临时数组
if (temp == NULL) {
printf("内存分配失败\n");
return;
}
mergeSort(arr, temp, 0, n - 1);
free(temp);
}
// 打印数组
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, 3, 2, 8};
int n = sizeof(arr) / sizeof(arr[0]);
printf("排序前: ");
printArray(arr, n);
optimizedMergeSort(arr, n);
printf("排序后: ");
printArray(arr, n);
return 0;
}
优化说明:
优化点 | 改进效果 | 适用场景 |
---|---|---|
预分配临时数组 | 减少内存分配次数,提升性能 | 大规模数据排序 |
小数组插入排序 | 减少递归深度,降低函数调用开销 | 子数组长度 ≤ 15 |
提前检查有序性 | 避免不必要的合并操作 | 输入数据部分有序 |
入口函数封装 | 简化调用逻辑,隐藏临时数组细节 | 通用 |