快速排序复杂度证明 及优化

本文深入探讨了快速排序算法,分析其在最坏、最好及平均情况下的时间复杂度,并讨论了如何通过优化提高效率。

快排是分治的思想,分解成小问题解决(排序),合并(排序过程都是在一个数组上直接操作,不用合并的过程)。

快速排序复杂度

最坏情况(O(n^2))

证明:最坏情况下就是对已经排好序的序列操作,假设是从小到大,那么last就会从最后一直比到first(哨兵位置)(共比较n-1次),并且将序列分为1和n-1,之后n-1以类似方式被递归划分。

假设算法每次都进行了这种不对称划分,划分的时间代价为θ(n)[//n是元素个数],因为对一个大小为0的数组递归调用后T(0)=θ(1)[//相当于只调用一次就会返回,不会进行更深层次的递归调用],算法的运行时间可以递归表示为:

 T(n)=T(n-1)+T(0)+θ(n)=T(n-1)+θ(n)

书上说是用代换法。代换法两步:1)假设解的形式  2)用数学归纳找出使解真正有效的常数。例如:

链接  (这个证明有错误)总的过程就是先根据经验猜测,然后代入推导。

此处证明:链接


所以T(n)=θ(n^2). 快速排序在最坏情况下的 运行时间是θ(n^2).最坏情况下并不比直接插入好。


最好情况(O(nlgn))

最好情况是在平均划分的情况下:

T(n)≤2T(n/2)+θ(n).

之所以是≤,是因为一个被划分为n/2取地板,另一个子问题大小为n/2取天棚减1.

这个使用主定理(the Master Theorem方法证明:

主定理:



//主变量定理证明我没看。

在T(n)≤2T(n/2)+θ(n)中,f(n)=θ(n)=cn.  a=2,b=2,所以使用第2条得T(n)=O(nlgn).

还讨论了,划分是9:1划分,得到的结果是运行时间也是θ(nlgn).主要原因是任意一种常数比例进行的划分都会产生深度为θ(lgn)得递归树。

平均情况θ(nlgn)

在平均情况下,好的划分和坏的划分是平均出现在划分树上的,当好、差划分交替在各层时,快排的运行时间就如全是好的划分一样,为θ(nlgn).


附知乎大佬回答:



//这个平均情况的公式不太理解

优化

//明天再来写,根据规模使用不同的排序算法+快排变形。



参考:百度百科+《算法导论》

<think>好的,用户想了解快速排序的时间复杂度。根据之前提供的引用内容,我需要综合这些信息给出详细的回答。首先,用户的问题明确,但可能需要分不同情况来阐述时间复杂度。 用户之前的问题是关于C++中的new和calloc,但当前问题转向了快速排序的时间复杂度。因此需要确保回答的结构清晰,覆盖平均、最好、最坏情况,并引用提供的参考资料。 引用1提到平均时间复杂度是O(n log n),最坏是O(n²),最好也是O(n log n)。引用3详细解释了最坏情况的发生条件,比如数组已经有序时选择不当的枢轴。引用2对比了不同排序算法的时间复杂度,指出快速排序平均O(n log n)和不稳定的特性,以及最坏情况下的O(n²)。 需要将这些信息整合,分点说明不同情况下的时间复杂度,并解释原因。同时,可能需要加入优化方法,如三数取中或随机选择枢轴,来避免最坏情况,这部分引用中没有提到,但根据常识补充可以增强回答的实用性。 还要注意用户可能存在的深层需求,比如如何在实际应用中优化快速排序,或者不同场景下的选择。但用户当前的问题集中在时间复杂度,所以重点应放在解释不同情况,并引用提供的资料。 需要检查是否有遗漏的信息,例如空间复杂度。引用2提到快速排序的空间复杂度是O(log n),这点可能也需要提及,但用户的问题仅针对时间复杂度,所以可能作为补充信息。 最后,确保回答结构符合用户之前示例中的格式,使用分点、加粗标题,引用对应的文献,并在末尾生成相关问题。需要避免使用Markdown格式,但保持清晰的结构。</think>### 快速排序的时间复杂度详解 快速排序的时间复杂度要取决于**分区操作(partition)的平衡性**,以下是具体分析: --- ### **1. 平均时间复杂度:$O(n \log n)$** 快速排序通过分治策略将数组划分为两个子数组,理想情况下每次分区都能将数组分成近似相等的两部分。此时递归深度为 $\log n$,每层需处理 $n$ 个元素,总操作次数为 $n \log n$。 **数学推导**: $$ T(n) = 2T\left(\frac{n}{2}\right) + O(n) $$ 根据定理(Master Theorem),解得 $T(n) = O(n \log n)$[^1][^3]。 --- ### **2. 最好时间复杂度:$O(n \log n)$** 当每次选择的枢轴(pivot)恰好将数组**均匀分割**时(例如选择中位数作为枢轴),递归树高度为 $\log n$,每层处理 $n$ 个元素,因此时间复杂度为 $O(n \log n)$[^1][^3]。 --- ### **3. 最坏时间复杂度:$O(n^2)$** 当每次分区**极不平衡**时(例如输入数组已有序且总选择第一个元素作为枢轴),递归树退化为链表,深度为 $n$,每层操作次数为 $n$,总时间复杂度为: $$ T(n) = T(n-1) + O(n) \implies O(n^2) $$ **典型场景**: - 输入数组已升序或降序排列 - 固定选择端点作为枢轴(如第一个或最后一个元素)[^3]。 --- ### **4. 优化避免最坏情况** 通过以下策略可**降低最坏情况发生概率**: 1. **随机选择枢轴**:每次随机选取数组中的一个元素作为枢轴。 2. **三数取中法**:选择数组首、中、尾三个元素的中位数作为枢轴。 3. **混合排序策略**:当递归深度超过阈值时,切换到堆排序或插入排序[^3]。 --- ### **5. 对比其他排序算法** | 排序算法 | 平均时间复杂度 | 最坏时间复杂度 | 稳定性 | 空间复杂度 | |------------|----------------|----------------|--------|----------------| | 快速排序 | $O(n \log n)$ | $O(n^2)$ | 不稳定 | $O(\log n)$[^2] | | 归并排序 | $O(n \log n)$ | $O(n \log n)$ | 稳定 | $O(n)$[^2] | | 堆排序 | $O(n \log n)$ | $O(n \log n)$ | 不稳定 | $O(1)$[^2] | --- ### **6. 实际应用中的表现** 尽管最坏时间复杂度为 $O(n^2)$,但快速排序在**实际应用中通常优于其他 $O(n \log n)$ 算法**,原因包括: - 缓存局部性:分区操作对内存访问更友好。 - 常数因子较小:相比归并排序,减少了数据复制的开销[^1][^3]。 --- ### **相关问题** 1. 如何证明快速排序平均时间复杂度是 $O(n \log n)$? 2. 哪些场景下应避免使用快速排序? 3. 快速排序的空间复杂度 $O(\log n)$ 是如何产生的? 4. 三数取中法具体如何实现?
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值