一、快速排序算法简介
快速排序(Quick Sort) 是一种基于分治思想(Divide & Conquer) 的高效排序算法,它的原理:是选一个基准值(pivot),把数组分成“比它小的”和“比它大的”两部分,然后递归排序。
为什么快速排序这么快?
核心原因有两点
- 每一轮都把问题规模一分为二
- 元素基本在“正确方向”移动,不做无效交换
平均情况下:
- 每一层处理 n 个元素
- 递归深度约为 log n
二、核心思想(分治法)
快速排序分为三步:
- 选基准(pivot)
- 分区(partition)
- 递归排序左右两边
示意:
[ < pivot | pivot | > pivot ]
pivot 只做一件事,把数组“一刀切”;每一层递归,pivot 都在“最终位置”
- pivot 左边:永远不会再跑到右边
- pivot 右边:永远不会再跑到左边
图示解析
假设数组:
[8, 3, 1, 7, 0, 10, 2, 12, 13, 16]
初始状态
索引: 0 1 2 3 4 5 6 7 8 9
数组: [8, 3, 1, 7, 0, 10, 2, 12, 13, 16]
- pivot = 8
- 左指针 i = 0
- 右指针 j = 9
第一轮分区(pivot = 8)
右指针向左找 < pivot 的数
16 > 8 ←
13 > 8 ←
12 > 8 ←
2 < 8 ✅ 停
把 2 填到 pivot 的位置(0 号位)
[2, 3, 1, 7, 0, 10, _, 12, 13, 16]
↑ 原来 2 的位置成“坑”
左指针向右找 > pivot 的数
3 < 8 →
1 < 8 →
7 < 8 →
0 < 8 →
10 > 8 ✅ 停
把 10 填到刚才的坑里
[2, 3, 1, 7, 0, _, 10, 12, 13, 16]
↑ 新坑
右指针继续向左
10 > 8 ✔
左右指针相遇,结束循环,把 pivot 放入最终位置:
[2, 3, 1, 7, 0, 8, 10, 12, 13, 16]
↑ pivot 就位
第一轮结果
[2, 3, 1, 7, 0] 8 [10, 12, 13, 16]
pivot = 8 已在最终正确位置
递归处理左半部分 [2, 3, 1, 7, 0]
选择 pivot = 2
[2, 3, 1, 7, 0]
从右找 < 2 → 0
[0, 3, 1, 7, _]
从左找 > 2 → 3
[0, _, 1, 7, 3]
从右找 < 2 → 1
[0, 1, _, 7, 3]
指针相遇,放回 pivot:
[0, 1, 2, 7, 3]
左半结果
[0, 1] 2 [7, 3]
递归处理 [7, 3]
pivot = 7
[7, 3]
从右找 < 7 → 3 放回 pivot:
[3, 7]
右半部分 [10, 12, 13, 16]
pivot = 10
[10, 12, 13, 16]
全部都 > 10,pivot 不动
继续递归:
- [12, 13, 16]
- pivot = 12 → 有序
- pivot = 13 → 有序
最终排序完成
[0, 1, 2, 3, 7, 8, 10, 12, 13, 16]
全过程结构图(总结版)
[8,3,1,7,0,10,2,12,13,16]
|
----------------------------------
| |
[2,3,1,7,0] [10,12,13,16]
| |
--------------- 已有序
| |
[0,1] [3,7]
三、完整示例
Hoare 分区法(效率高,工程常用)
int partition(int arr[], int left, int right)
{
int pivot = arr[left];
int i = left - 1;
int j = right + 1;
while (true)
{
do { i++; } while (arr[i] < pivot);
do { j--; } while (arr[j] > pivot);
if (i >= j)
return j;
swap(arr[i], arr[j]);
}
}
递归:
void quickSort(int arr[], int left, int right)
{
if (left < right)
{
int p = partition(arr, left, right);
quickSort(arr, left, p);
quickSort(arr, p + 1, right);
}
}
2238

被折叠的 条评论
为什么被折叠?



