一、 快速排序的描述
1、 快速排序是一种原地排序的算法,最坏情况下的时间复杂度为Θ(n^2),期望的运行时间为Θ(n logn),且其中隐含的常数因子较小。
2、 快速排序分三个步骤:
分解:数组A[p...r]被划分成两个数组A[p...q-1]和A[q+1...r],使得A[p...q-1]中的元素都小于等于A[q],A[q+1...r]中的元素都大于等于A[q]。下标q在这个划分过程中计算。
解决:递归调用快速排序,对子数组A[p...q-1]和A[q+1...r]进行排序。
合并:两个子数组是就地排序,不需要其他操作,整个数组就已经排好。
Quick-Sort(A, p, r) 1 if p < r 2 then q <-- Partition(A, p, r) 3 Quick-Sort(A, p, q-1) 4 Quick-Sort(A, q+1, r)
Partition(A, p, r) 1 x <-- A[r] 2 i <-- p-1 3 for j <-- p to r-1 4 do if A[j] < x 5 i <-- i + 1 6 A[i] <--> A[j] 7 exchange A[i+1] <--> A[r] 8 return i+1Partition的执行时间为O(n)
3、循环不变式
a、 若p ≤k ≤i, 则A[k] ≤x.
b、 若i + 1 ≤k ≤j -1, 则A[k] > x.
c、 若k = r, 则A[k] = x.
二、 快速排序的性能
快速排序的运行时间与划分是否对称有关,我们分别就以下三种情况进行讨论:
1、 最坏情况划分:快速排序的最坏情况划分行为发生在划分过程产生的两个区域分别包含n-1个元素和1个元素的时候。
假设算法的每一次递归调用中都出现了这种不对称划分。划分的时间代价为Θ(n)
T(n)=T(n-1)+T(0)+Θ(n)=T(n-1)+Θ(n)
可以证明T(n)=Θ(n^2)
2、 最佳情况划分:在PARTITION可能做的最平衡的划分中,得到的两个子问题的大小都不大可能 大于n/2。
在这种情况下,快速排序运行的速度要快的多。这时,表达其运行时间的递归式为
T(n)≤2T(n/2)+Θ(n)
根据主定理,该递归式的解为:T(n)=O(nlgn)
3、 平衡的划分:假设划分过程总是产生9:1的划分,乍一看这种划分很不平衡,这时快速排序的递归式为
T(n)≤T(9n/10) + T(n/10) + cn
树的每一层都有代价cn,直到在深度log10 n=Θ (lgn)处达到边界条件,以后各层代价至多为cn。
递归于深度log10/9 n=Θ(lgn)处结束。快速排序的总时间代价为T(n)=Θ(nlogn),从渐进意义上看就和划分是在中间进行的一样。
事实上,即使是99:1的划分时间代价也为Θ(nlogn)。
任何一种按常数比例进行划分所产生的递归树的深度都为Θ(lgn),其中每一层的代价为O(n),因而不管常数比例
是什么,总的运行时间都为Θ(nlogn),只不过其中隐含的常数因子有所不同。
从直觉上看,差的划分的代价Θ(n)可被吸收到好的划分的代价Θ(n)中去,结果是一个好的划分。这样,当好、差
划分交替分布划分都是好 的一样:仍是Θ(nlogn),但Θ记号中隐含的常数因子要略大一些。
三、 快速排序的随机化版本
我们假定输入数据的所有排列都是等可能的。但在实际应用中,这个 假设就不会总是成立。解决的方法是,利用
随机化策略,能够克服分布的等可能性假设所带来的问题。
1、 快速排序的随机化版本有一个和其他随机化算法一样的有趣性质:没有一个特别的输入会导致最坏情况性态。
2、 随机算法的最坏情况性态是由随机数产生器决定的:事实上可以证明几乎所有的排列都可使快速排序接近平均情况性态,只有非常少的几个排列才会导致算法的近最坏情况性态。
3、 在这里,我们采用随机采样的随机化技术,从子数组A[p..r]中随机选择一个元素,即将A[r]与从A[p..r]中随机选出的一个元素交换。在这一修改中,我们是从p,…,r这一范围中随机取样的,确保了在子数组的r-p+1个元素中,主元元素x=A[r]等可能地取其中的任何一个。
Randomized-Partition(A, p, r) 1 i<--Random(p, r) 2 exchange A[r] <--> A[i] 3 return Partition(A, p, r) Randomized-Quick-Sort(A, p, r) 1 if p < r 2 then q <-- Randomized-Partition(A, p, r) 3 Randomized-Quick-Sort(A, p, q-1) 4 Randomized-Quick-Sort(A, q+1, r)
四、 快速排序的分析
1、 最坏情况分析:前面从直觉上可以判断出最坏情况发生在每次划分过程产生的两个区间分别包含n-1个元素和1个元素的时候(设输入的表有n个元素)。下面我们来证明这种每次划分过程产生的两个区间分 别包含n-1个元素和1个元素的情况就是最坏情况。
设T(n)是过程Quick_Sort作用于规模为n的输入上的最坏情况的时间,则
我们假设T(n)≤cn^2, 其中c 为常数。将归纳假设代入上式,得到:
于是有,
只要c足够大,上面的第二个小于等于号就可以成立。这样快速排序最坏情况为Θ(n^2).
2、 平均情况分析:QUICKSORT的运行时间是由花在过程PARTITION上的时间所决定的。每当PARTITION过程被调用时,就要选出一个主元素。于是最多调用这个过程n次。只要知道第4行执行次数,就可以知道QUICKSORT中for循环所化时间。
引理 设当QUICKSORT在一个包含n个元素的数组上运行时,PARTITION在第四行所做比较次数为X。那么,
QUICKSORT的运行时间为O(n+X)。
证明: 根据上面的讨论,对PARTITION的调用共有n次,每一次调用都需做固定量的工作,再执行若干次for循环。在for循环的每一轮迭代中,都需要执行第4行。
我们定义指示器随机变量Xij = I{zi与zj进行比较},由于每个元素只和主元元素进行比较,而且之后该主元元素不会再跟其他元素比较了,因此 总的比较次数:
对上式求期望:
在中的某一元素被选为主元之前,集合整 个都是在统一划分中的。于是, 中的任何元素 都会等可能地被首先选为
主元。因为集合 中 共有j-i+1个元素,还因为主元是随即独立选取的,所以,任何元素被首先选为主元的概率是 1/(j-i+1)于是
综合起来则有:
算法导论——lec 07 快速排序,布布扣,bubuko.com
原文地址:http://blog.csdn.net/uilotus/article/details/37331271