排序算法【2】——快速排序
算法描述
快速排序采用了分治的思想:
- 分解:数组被划分为两个子数组和,使得中的元素小于等于,中的元素大于等于
- 解决:通过递归调用快速排序,对子数组和进行排序
伪代码
在不同的快速排序算法实现中有不同的分区PARTITION
策略
QUICKSORT(A, p, r)
if p < r
q = PARTITION(A, p, r)
QUICKSORT(A, p, q - 1)
QUICKSORT(A, q + 1, r)
PARTITION(A, p, r)
i = RANDOM(p, r)
exchange A[r] with A[i]
x = A[r]
i = p - 1
for j = p to r - 1
if A[j] <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i + 1] with A[r]
return i + 1
算法复杂度
这里假设数组中元素互不相同
- 最好情况:每次分区的时候,两边的分区大小一致,那么最多递归层,每一层都会比对次,所以时间复杂度为
- 最坏情况:每次分区选的主元都是当前数组中的最大值或者最小值,那么会递归层,时间复杂度为
- 平均情况:令随机变量表示整个快速排序过程中比对次数,那么,所以时间复杂度为
期望的计算过程:
令随机变量
注意到,元素和最多只会发生一次比较(比较之后主元不会进入分区),所以
同时与发生比较的概率,就是元素或者作为区间中第一个被选取的主元,这一概率
所以
Hoare分区
在上面朴素的分区策略中,无法将与主元相等的元素平均地划分到左右子区间,Hoare分区策略解决了这个问题,那就是从两边开始扫描:
HOARE-PARTITION(A, p, r)
i = RANDOM(p, r)
pivot = A[i]
p = p - 1
while true
while A[++p] < pivot
while pivot < A[--r]
if p < r
exchange A[p] with A[r]
else
return p
实际上,std::sort
采用的也是这种方式,所以C++标准规定了传入的比较函数必须保证,比如:
int n = 10000000;
std::vector<int> vec(n);
std::sort(vec.begin(), vec.end(), [] (int x, int y) {
return x <= y;
});
上面的代码会造成内存越界,从而segmentfault
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)