C 语言快速排序详解:从基础到非递归实现
快速排序是 C 标准库中内置的高效排序算法,其核心在于分治思想与基准值选取。本文详细拆解了 Hoare 分区方案的实现逻辑,通过双指针扫描完成区间划分。针对极端数据场景,阐述了三数取中法如何规避最坏时间复杂度,以及小区间内采用堆排序替代递归的优化策略。此外,还展示了利用显式栈模拟递归调用的非递归实现,有效防止深层递归引发的栈溢出问题。
一、快速排序(初阶)
1. 算法思想
快速排序有一个 key 值,称为基准元素。在第一次快速排序结束后,这个 key 的位置会发生改变,其他元素位置也会相应调整。最终,在 key 的左边都是小于 key 的数,右边都是大于 key 的数。此时 key 的顺序就被排好了,后续不需要再动。
接着将整个数组以 key 分成左右两个区间,并在这两个区间循环执行上述步骤。直到区间不可再分(区间只剩一个元素),排序结束。
简单来说,快速排序就是不断将比 key 小的数放左边,把比 key 大的数放右边,最后完成排序。
2. 实现思路
(1)定 key 值
第一步确定 key 值,通常理解为第一个数字(后续会改进)。后续的排序围绕这个基准元素进行。
(2)大小交换
使用两个指针,一个从左往右走,一个从右往左走。
- 右指针向左走,直到遇到比
key小的数停下。 - 左指针向右走,直到遇到比
key大的数停下。 - 两指针停下后,交换对应的值,大的换到右边,小的换到左边。
(3)循环
两指针继续移动,满足条件时继续交换,直到相遇,循环停止。
(4)交换 key
将 key 与两指针相遇点的值进行交换。此时 key 左边都小于它,右边都大于它,第一轮快速排序结束。
(5)分割区间
将 key 左右的区间分割开来,分别对这两个区间重复第一轮的排序步骤。
(6)结束
当每个区间分割成只剩下一个元素时,跳出循环。所有区间处理完毕,排序完成。
3. 实现代码
void QuickSort1(int* a, int left, int right) {
if (left >= right) // 判断是否继续,当区间只有一个数时跳出循环
return;
int key = left; // 确定 key 的值,为第一个元素
int L = left;
int R = right; // 先将左右的下标记录下来,以免后面丢失
while (left < right) { // 当左右小人相遇时就停止循环
while (left < right && a[right] >= a[key])
right--;
(left < right && a[left] <= a[key])
left++;
Swap(&a[left], &a[right]);
}
Swap(&a[right], &a[key]);
key = right;
QuickSort1(a, L, key - );
QuickSort1(a, key + , R);
}


