算法进阶必备!今日解锁高效排序算法——快速排序,双版本代码+复杂度优化分析,带你领略分治思想的精妙。
一、快速排序核心思想
快速排序(Quick Sort)由Tony Hoare于1959年提出,采用分治策略:
通过选定基准值(pivot),将数组分割为两个子序列,递归排序后合并实现整体有序。
算法特性:
-
不稳定排序(相同元素可能改变顺序)
-
平均时间复杂度:O(n log n)
-
最坏时间复杂度:O(n²)(可通过优化避免)
-
空间复杂度:O(log n)(递归栈)
二、算法原理图解
三步核心流程:
-
选基准:从数组中选取一个元素作为基准值(pivot)
-
分区操作:将数组分为三部分(< pivot,== pivot,> pivot)
-
递归排序:对左右子数组递归执行上述操作
三、C++代码实现
基础递归版本
#include <iostream>
using namespace std;
// 分区函数(Lomuto方案)
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // 选取最后元素为基准
int i = low - 1; // 小于基准的边界指针
for (int j = low; j < high; ++j) {
if (arr[j] <= pivot) {
++i;
swap(arr[i], arr[j]);
}
}
swap(arr[i+1], arr[high]);
return i + 1; // 返回基准最终位置
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
// 示例用法
int main() {
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr)/sizeof(arr[0]);
quickSort(arr, 0, n-1);
cout << "排序结果:";
for (int i=0; i<n; ++i)
cout << arr[i] << " ";
return 0;
}
迭代优化版本(避免递归栈溢出)
#include <stack>
void quickSortIterative(int arr[], int low, int high) {
stack<int> s;
s.push(low);
s.push(high);
while (!s.empty()) {
high = s.top(); s.pop();
low = s.top(); s.pop();
int pi = partition(arr, low, high);
if (pi - 1 > low) {
s.push(low);
s.push(pi - 1);
}
if (pi + 1 < high) {
s.push(pi + 1);
s.push(high);
}
}
}
关键点解析:
-
partition()
函数实现核心分区逻辑 -
Lomuto方案 vs Hoare方案(本文采用更易理解的Lomuto)
-
递归终止条件
low < high
-
迭代版本使用显式栈模拟递归过程
四、实例演算
以数组[3, 0, 2, 5, 1]
为例(选择最后一个元素为pivot):
首次分区过程:
初始数组:[3, 0, 2, 5, 1](pivot=1)
第1次比较:3 > 1 → 不交换(i=-1, j=0)
第2次比较:0 ≤ 1 → i=0,交换arr[0]和arr[1]
当前数组:[0, 3, 2, 5, 1]
第3次比较:2 > 1 → 不交换
第4次比较:5 > 1 → 不交换
最终交换基准位置:[0, 1, 2, 5, 3]
返回基准位置:1
五、复杂度与优化
情况 | 时间复杂度 | 空间复杂度 | 解决方案 |
---|---|---|---|
最佳情况 | O(n log n) | O(log n) | 平衡分区 |
最差情况 | O(n²) | O(n) | 随机化选择pivot |
平均情况 | O(n log n) | O(log n) | 三数取中法 |
常见优化策略:
-
随机化pivot选择:避免有序数组的最坏情况
int random = low + rand() % (high - low); swap(arr[random], arr[high]);
-
三数取中法:取首、中、尾的中位数作为pivot
-
插入排序混合:当子数组长度较小时切换排序算法
六、总结与进阶
优势:
-
平均性能最好的O(n log n)排序算法
-
内存访问模式对缓存友好
-
可并行化优化(多线程处理子数组)
局限:
-
递归实现可能栈溢出
-
不稳定排序特性
-
最坏情况需通过优化避免