本文已参与[新人创作礼]活动,一起开启掘金创作之路
快速排序(不稳定)
简单回顾一下快速排序(以从小到大排序为例):
①在一个数组[p,q]中选取一个元素 r ,使得新划分的两个数组,其中[p...r-1]都小于r,[r+1...q]都大于 r
②递归调用上述方法继续划分[p...r-1]和[r+1...q]
性能分析:
最坏情况: 如果每次划分的时候都是 数组1、和空数组 即 划分出来的子问题分别包含了 n-1个元素、和0个元素 ,那么此时快速排序是最坏情况。我们令划分操作的时间复杂度为 Θ(n),则T(0)= Θ(1),那么运行时间递归式可表示为
T(n)= T(n-1)+ T(0)+Θ(n) = T(n-1)+Θ(n) ,通过代入法可得出T(n)=Θ(n^2^)
(以从小到大排序为例)如果每次选中的 r 正好是整个数组中最大的,那么此时出现最坏情况
最好情况: 划分的两个数组的元素个数都是 floor(n/2)时,此时性能极佳,递归式可以表示为
T(n)=2* T(n/2)+Θ(n) ,根据主值定理可以求出 T(n)=Θ(nlgn)
平衡的划分: 将划分按照一定的比例划分,比如 9:1 ,此时的递归树如下
我们可以根据(9/10)^x^ n= 1 轻易的算出树最高为 x = log
10/9n
我们可以将递归式表示为
T(n)= T(9n/10)+T(n/10)+ Θ(n)
我们令Θ(n) = cn ,T(n)≤ dnlgn,因此我们可以得到
T(n)≤ dnlgn - dn(lg10-9/10lg9) + cn (中间过程省略,就是将上面两个式子带入)
因此当 dn(lg10-9/10lg9) ≥ cn 时,即d≥c/(lg10-9/10lg9)时
T(n)≤ dnlgn ,因此我们可以得到运行时间是O(nlgn)
划重点!实际上所有的平衡划分(划分是常数比例),算法的运行时间总是O(nlogn)
堆排序(不稳定)
简单回顾一下堆排序(以从小到大排序(大根堆)为例): 大根堆的性质:根节点的值大于左右任一孩子的值(这是我们算法的核心) 运行过程: ①将元素组初始化为大根堆 ②(将元素进行大根堆排序,剔除位于堆顶的节点,并将堆底部最后一个元素置于堆顶,将剩余的节点进行大根堆排序)<—循环此过程,就可以不断的将每次最大的元素挑出来,直到元素个数为0。
性能分析:
从运行过程描述中可以看出
①构建初始堆经推导复杂度为O(n)
②交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质,[log2(n-1),log2(n-2)...1]逐步递减,近似为nlogn
计算过程如下:
我们从上面的计算可以看出log
2n!和nlog2n是同级的(因为比值为1)
划重点!因此我们可以得出堆排序的时间复杂度 O(nlogn)