快速排序详解与优化实现
快速排序(Quick Sort)是 C 标准库中内置的高效排序算法,基于分治思想。相比插入排序和希尔排序,它在平均情况下的性能表现更为优异。本文将深入解析其核心原理,从基础 Hoare 分区法到多种工程优化策略,并提供完整的 C 语言代码实现。
算法思想
快速排序的核心在于选择一个基准值(Key),通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分小,然后再分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
具体流程如下:
- 选取基准:通常选择数组第一个元素作为 Key。
- 分区操作:设置两个指针,分别从两端向中间扫描。右指针向左找小于 Key 的数,左指针向右找大于 Key 的数,找到后交换。直到两指针相遇。
- 交换基准:将相遇点的值与 Key 交换,此时 Key 左侧均小于它,右侧均大于它。
- 递归处理:对 Key 左右两个区间重复上述步骤,直到区间不可再分。
初阶实现
在基础版本中,我们直接选取首元素作为基准。虽然逻辑简单,但在特定数据分布下效率会下降。
void QuickSort1(int* a, int left, int right) {
if (left >= right) {
return;
}
int key = left;
int L = left;
int R = right;
while (left < right) {
// 右指针向左走,直到找到比 key 小的值
while (left < right && a[right] >= a[key]) {
right--;
}
// 左指针向右走,直到找到比 key 大的值
while (left < right && a[left] <= a[key]) {
left++;
}
Swap(&a[left], &a[right]);
}
Swap(&a[right], &a[key]);
key = right;
QuickSort1(a, L, key - 1);
QuickSort1(a, key + 1, R);
}
中阶优化:三数取中
当数组已经有序或接近有序时,若始终选取首元素为 Key,会导致划分极度不平衡,时间复杂度退化为 O(N^2)。为了避免这种情况,可以采用'三数取中'法。
即取数组的开头、中间、结尾三个数,将大小居中的那个数作为 Key。这样能有效避免极端值被选为基准。
// 三数取中,返回三个数的中间值的下标
int FindKey(int* a, int left, int right) {
int mid = (left + right) / ;
(a[left] > a[right]) {
(a[right] > a[mid]) {
right;
} (a[mid] > a[left]) {
left;
} {
mid;
}
} {
(a[left] > a[mid]) {
left;
} (a[mid] > a[right]) {
right;
} {
mid;
}
}
}


