| 上一篇 | 下一篇 |
|---|---|
目 录
-
- [3)快速排序(Quick Sort)](#3)快速排序(Quick Sort))
-
- 3.1)核心思想
- 3.2)算法步骤(升序)
- 3.3)时间与空间复杂度
- [3.4)C 语言代码示例](#3.4)C 语言代码示例)
3)快速排序(Quick Sort)
快速排序是一种高效的分治排序算法,由 Tony Hoare 于 1960 年提出。
3.1)核心思想
核心思想是:选一个"基准值"(pivot),将数组划分为两部分:
- 左边:所有元素 ≤ 基准值
- 右边:所有元素 ≥ 基准值
- 然后 递归地对左右两部分分别排序。
整个过程采用 "分而治之" 策略。
3.2)算法步骤(升序)
- 选择基准值(pivot):通常选首元素、尾元素或中间元素;
- 分区:
- 重新排列数组,使得比 pivot 小的在左边,大的在右边;
- 最终 pivot 被放到其最终正确位置;
- 递归处理:
- 对 pivot 左侧子数组递归快排;
- 对 pivot 右侧子数组递归快排;
- 递归终止条件:子数组长度 ≤ 1(自然有序)。
简单说就是: 先选个基准值(首元素/尾元素/中间元素等),然后小于它的放左边(左分区),大于它的放右边(右分区),此时这个基准值就处于正确位置了;然后左分区和右分区分别再各自选个基准值,再分区......递归循环;最后当没有分区可分了,那么就是有序了。
3.3)时间与空间复杂度
| 情况 | 时间复杂度 |
|---|---|
| 最好/平均 | O(n log n) |
| 最坏 | O(n²) ------ 如每次选到最大/最小值作 pivot(如已排序数组) |
- 空间复杂度:O(log n)(递归调用栈深度,平均情况);最坏 O(n)
- 稳定性:❌ 不稳定(分区过程中可能改变相等元素的相对顺序)
- 原地排序:是(仅使用少量额外空间)
实际工程中常通过 随机化 pivot 或 三数取中法 避免最坏情况。
3.4)C 语言代码示例
分区方法有很多,这里采用经典的 左右指针法(Hoare 分区),效率较高(看参考视频就明白了)。
c
#include <stdio.h>
/**
* @brief: partition ------ 分区函数:返回 pivot 的最终位置
* @note: low - 当前要处理的子数组的起始下标; high - 当前要处理的子数组的结束下标
*/
int partition(int arr[], int low, int high) {
int pivot = arr[low]; // 选择第一个元素作为 pivot
int left = low;
int right = high;
while (left < right) {
// 从右往左找第一个 <= pivot 的元素
while (left < right && arr[right] >= pivot)
right--;
// 从左往右找第一个 >= pivot 的元素
while (left < right && arr[left] <= pivot)
left++;
// 交换两个错位的元素
if (left < right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
// 将 pivot 放到正确位置(与 left/right 重合处交换)
arr[low] = arr[left];
arr[left] = pivot;
return left; // 返回 pivot 的索引
}
// 快速排序主函数
void quick_sort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high); // 获取分区点
quick_sort(arr, low, pi - 1); // 递归排序左半部分
quick_sort(arr, pi + 1, high); // 递归排序右半部分
}
}
// 打印数组
void print_array(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 主函数:测试快速排序
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原始数组: ");
print_array(arr, n);
quick_sort(arr, 0, n - 1);
printf("排序后数组: ");
print_array(arr, n);
return 0;
}
运行结果如下:
原始数组: 64 34 25 12 22 11 90
排序后数组: 11 12 22 25 34 64 90