数据结构:快速排序进阶优化
在之前的实现中,我们完成了递归与非递归版本的快速排序,并学习了三种基准选择方法。但在实际场景中,面对大量重复元素或近乎有序的数据时,传统快排的性能会显著下降。本文将通过几种进阶策略来优化快速排序,提升其在复杂数据下的表现。
一、基准选择的优化
1. 三数取中法
原理: 从子数组的首、尾、中间三个位置选取中位数作为基准。这能有效避免极端值(如最大/最小值)被选为基准,从而平衡左右子数组的划分。
核心逻辑:
- 计算中间索引
mid = left + (right - left) / 2; - 比较
arr[left]、arr[mid]、arr[right]; - 将中位数交换到合适位置(通常是
left)。
// 三数取中函数
int threewaymid(int* arr, int left, int right) {
int mid = left + (right - left) / 2;
if (arr[left] > arr[right]) swap(&arr[left], &arr[right]);
if (arr[mid] > arr[right]) swap(&arr[mid], &arr[right]);
if (arr[mid] < arr[left]) swap(&arr[mid], &arr[left]);
return mid;
}
2. 随机数选择法
原理: 在 [left, right] 范围内随机选择一个元素作为基准。利用随机性打破固定模式,防止针对特定输入(如已排序数组)构造的最坏情况。
核心逻辑:
- 生成范围内的随机整数作为索引;
- 将随机选中的元素与首元素交换。
// 随机数取法示例
srand((unsigned int)time(NULL));
int randi = left + rand() % (right - left + 1);
swap(&arr[left], &arr[randi]);
3. 方案对比与建议
- 优先选择三数取中: 在多数存在部分有序数据的场景下,其划分更稳定且无随机数生成的开销。C 语言标准库
qsort常采用类似优化。 - 随机数法的补充场景: 当数据分布完全未知或需防御对抗性输入时,随机选择更安全。
二、三路划分处理重复元素
当数组中存在大量与基准值相同的元素时,传统的二路划分会导致分割失衡。三路划分将数组分为'小于基准'、'等于基准'、'大于基准'三部分,显著提升此类场景的效率。
核心逻辑:


