归并排序与快速排序的简单实现(C语言)
文章目录
- 归并排序与快速排序的简单实现(C语言)
- 一、归并排序实现
- 核心思想
- 关键特性
- C语言实现
- 二、快速排序实现
- 核心思想
- 关键特性
- C语言实现
- 三、算法对比分析
- 四、总结
归并排序与快速排序的简单实现(C语言)
一、归并排序实现
核心思想
采用分治策略的三步走:
- 分解:递归将数组二分至单个元素
- 解决:单个元素自然有序
- 合并:有序子数组合并为完整数组
关键特性
- 稳定排序(相等元素顺序不变)
- 时间复杂度:
O(n log n)
- 空间复杂度:
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++];
} else {
arr[k++] = R[j++];
}
}
// 拷贝剩余元素
while (i < n1) arr[k++] = L[i++];
while (j < n2) arr[k++] = R[j++];
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);
}
}
二、快速排序实现
核心思想
通过分区操作实现就地排序:
- 选基准:选择数组元素作为基准值(pivot)
- 分区:将数组分为小于基准和大于基准的两部分
- 递归:对子数组重复上述过程
关键特性
- 平均时间复杂度
O(n log n)
- 最坏情况
O(n²)
(可通过优化避免) - 原地排序(空间复杂度
O(log n)
) - 不稳定排序
C语言实现
// 交换两个元素
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 分区函数(Lomuto方案)
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // 选择最后一个元素作为基准
int i = low - 1; // 小于基准的边界索引
for (int j = low; j <= high - 1; j++) {
if (arr[j] <= pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return i + 1;
}
// 递归排序函数
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
// 优化版基准选择(三数取中法)
int medianOfThree(int arr[], int low, int high) {
int mid = low + (high - low)/2;
if (arr[low] > arr[mid]) swap(&arr[low], &arr[mid]);
if (arr[low] > arr[high]) swap(&arr[low], &arr[high]);
if (arr[mid] > arr[high]) swap(&arr[mid], &arr[high]);
return mid;
}
三、算法对比分析
特性 | 归并排序 | 快速排序 |
---|---|---|
时间复杂度 | 稳定O(n log n) | 平均O(n log n) ,最差O(n²) |
空间复杂度 | O(n) | O(log n) |
稳定性 | 稳定 | 不稳定 |
最佳场景 | 链表/大数据集/需要稳定性 | 内存排序/随机数据 |
缓存利用率 | 较差(频繁创建临时数组) | 优秀(就地排序) |
实现复杂度 | 较高(需要合并操作) | 较低(分区策略简单) |
四、总结
「稳链外,选归并;快省效,用快排」
- 稳(稳定性) / 链(链表) / 外(外部数据) → 归并排序
- 快(速度) / 省(内存) / 效(效率) → 快速排序