快速排序是数据结构中分治思想的经典应用,凭借平均时间复杂度O(nlogn)、原地排序的特性,成为实际开发中常用的排序算法之一。
一、快速排序C++完整代码
#include <iostream>
#include <vector>
using namespace std;
// 划分函数:选择基准元素,将数组分为"小于基准"和"大于基准"两部分
int partition(vector<int>& arr, int left, int right) {
// 选择数组最右侧元素作为基准(可优化为随机选择,避免最坏情况)
int pivot = arr[right];
// i指向"小于基准区域"的最后一个元素,初始为左边界前一位
int i = left - 1;
// 遍历除基准外的所有元素
for (int j = left; j < right; j++) {
// 若当前元素小于基准,将其归入"小于基准区域"
if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]); // 交换元素,扩展"小于基准区域"
}
}
// 将基准元素放到最终位置("小于基准区域"和"大于基准区域"中间)
swap(arr[i + 1], arr[right]);
return i + 1; // 返回基准元素的索引,用于后续分治
}
// 快速排序主函数(递归实现)
void quickSort(vector<int>& arr, int left, int right) {
// 递归终止条件:当子数组长度为1或0时,无需排序
if (left < right) {
// 1. 划分:获取基准元素位置,完成一次局部排序
int pivotIndex = partition(arr, left, right);
// 2. 分治:递归排序基准左侧的子数组(均小于基准)
quickSort(arr, left, pivotIndex - 1);
// 3. 分治:递归排序基准右侧的子数组(均大于基准)
quickSort(arr, pivotIndex + 1, right);
}
}
// 测试函数:打印数组
void printArray(const vector<int>& arr) {
for (int num : arr) {
cout << num << " ";
}
cout << endl;
}
int main() {
// 测试用例1:无序数组
vector<int> arr1 = {3, 1, 4, 1, 5, 9, 2, 6};
cout << "排序前(无序数组):";
printArray(arr1);
quickSort(arr1, 0, arr1.size() - 1);
cout << "排序后(无序数组):";
printArray(arr1);
// 测试用例2:含重复元素的数组
vector<int> arr2 = {5, 3, 8, 3, 2, 7, 5};
cout << "\n排序前(含重复元素):";
printArray(arr2);
quickSort(arr2, 0, arr2.size() - 1);
cout << "排序后(含重复元素):";
printArray(arr2);
// 测试用例3:已有序数组(验证基准选择优化的必要性)
vector<int> arr3 = {1, 2, 3, 4, 5, 6};
cout << "\n排序前(已有序数组):";
printArray(arr3);
quickSort(arr3, 0, arr3.size() - 1);
cout << "排序后(已有序数组):";
printArray(arr3);
return 0;
}
二、优快云博客撰写框架(含核心内容建议)
一篇优质的算法类优快云博客,需兼顾“原理易懂”“代码可跑”“拓展实用”,建议按以下结构撰写:
1. 标题(吸睛且明确)
• 推荐格式:数据结构实战 | 快速排序(C++实现):原理、代码与优化技巧
• 作用:让读者一眼明确“算法名称+实现语言+核心价值”,提升搜索曝光率。
2. 引言(为什么学这个算法)
• 核心内容:
◦ 快速排序的地位:对比冒泡排序(O(n²))、归并排序(需额外空间),说明其“高效+省空间”的优势;
◦ 应用场景:实际开发中对大规模数据的排序(如数据库查询结果排序、日志时间戳排序);
◦ 本文目标:帮读者“搞懂分治逻辑”“跑通代码”“避开常见坑”。
3. 快速排序核心原理(图文结合更清晰)
• 用“生活化类比”解释分治思想:
像整理书架时,先选一本“基准书”(如《算法导论》),把比它薄的放左边,比它厚的放右边;再对左右两堆书分别重复这个过程,直到每堆只剩一本书。
• 分3步拆解执行流程(配手绘图或动图更佳):
1. 选择基准:代码中选最右侧元素,可补充“随机选基准”“三数取中(左、中、右选中间值)”的优化逻辑;
2. 划分数组:遍历数组,将元素按“小于基准/大于基准”分到两侧,最后将基准放到中间;
3. 递归排序:对基准左右的子数组重复上述步骤,直到子数组无法再拆分。
4. 代码解析(逐模块讲透)
• 按“功能模块”拆分讲解,避免直接贴完整代码:
◦ partition函数:重点讲“i指针的作用”(标记小于基准区域的边界)和“交换逻辑”(如何确保区域划分正确);
◦ quickSort函数:讲递归终止条件(left < right)和分治的核心(基准左右分别排序);
◦ main函数:说明测试用例设计思路(覆盖无序、重复元素、已有序场景,验证算法稳定性和边界情况)。
• 关键提醒:标注“易踩坑点”,如“未将输入转换为vector导致越界”“递归时基准索引未±1导致死循环”。
5. 算法性能分析(体现专业性)
• 用表格清晰呈现,对比不同场景下的性能:
| 指标 | 结果 | 说明 |
|---------------------|-----------------------|---------------------------------------|
| 平均时间复杂度 | O(nlogn) | 每次划分将数组拆分为2个近似等长的子数组 |
| 最坏时间复杂度 | O(n²) | 已有序数组+选边界为基准(可通过优化规避) |
| 空间复杂度 | O(logn)~O(n) | 递归栈开销(平均O(logn),最坏O(n)) |
| 稳定性 | 不稳定 | 交换时可能打乱相同元素的相对顺序 |
6. 优化方向(进阶拓展)
• 提供3个可落地的优化方案,让博客更有深度:
1. 基准选择优化:用“三数取中”(左、中、右三个位置的元素选中间值)替代固定选右边界,避免最坏时间复杂度;
2. 小数组优化:当子数组长度小于10时,改用插入排序(减少递归开销,插入排序对小数组更高效);
3. 重复元素优化:用“三路快排”(将数组分为“小于基准”“等于基准”“大于基准”三部分),避免重复元素多次参与排序。
7. 总结与思考(收尾升华)
• 总结核心:快速排序的本质是“分治+基准划分”,高效的关键在于“均匀划分数组”;
• 引导思考:让读者尝试实现“非递归版快速排序”(用栈模拟递归栈),或对比归并排序的适用场景,提升互动性
736

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



