笔记
本节只给出快速排序运行时间的简单分析。快速排序的运行时间取决于PARTITION划分是否平衡,而划分的平衡与否又取决于用于划分的主元的选择。
1. 最坏情况时间复杂度
对于一个含
个元素的数组,PARTITION划分的最坏情况为:划分产生的两个子数组的大小分别为
和
时。假设快速排序每一次递归调用PARTITION都产生了最坏情况划分,那么算法的运行时间
满足以下递归式。
求解这个递归式得到
。也就是说,如果快速排序的每一次递归调用都产生了最坏情况划分,那么算法的时间复杂度为
。
快速排序最坏情况的一个例子是,输入数组已经完全有序,此时快速排序的时间复杂度为
。而同样的情况下,如果采用插入排序,时间复杂度为
。因此,在数组已经有序的时候,插入排序要优于快速排序。
2. 最好情况时间复杂度
快速排序的最好情况出现在:每一次PARTITION都得到一个完全平衡的划分,即对于一个含
个元素的数组,PARTITION产生的两个子数组的大小分别为
和
。假设快速排序每一次递归调用都产生了最好情况划分,那么算法的运行时间
满足以下递归式。
求解这个递归式得到
,这就是快速排序最好情况的时间复杂度。
3. 平均情况的时间复杂度
本节给出了结论:快速排序的平均情况时间复杂度为
。本节对这一结论只做了简要的说明,在7.4节会给出严格的证明,我们先记下这个结论。
练习
7.2-1 利用代入法证明:正如7.2节开头提到的那样,递归式
的解为
。
略
7.2-2 当数组
的所有元素都具有相同的值时,QUICKSORT的时间复杂度是什么?
解
利用练习7.1-2的结论,当所有元素都相同时,每次调用PARTITION都产生一个最坏情况划分,因此这种情况下,QUICKSORT的时间复杂度为
。
7.2-3 证明:当数组
包含的元素各不相同,并且是按降序排列的时候,QUICKSORT的时间复杂度为
。
解
考虑包含
个元素的数组
,其中元素各不相同,并且按降序排列,即
。我们来分析每次调用PARTITION的情况。
第
次划分,调用
,由于被选为划分主元的
是最小的,所以最终
与
交换,产生最坏情况划分。
第
次划分,调用
,由于被选为划分主元的
是最大的,所以这次划分没有任何改变,也是一个最坏情况划分。
接下来的第
次划分,调用
,此时数组
又是一个降序排列的数组,因此也产生一个最坏情况划分。
如此循环往复下去,每次调用
都产生一个最坏情况划分。所以数组按降序排列的情况下,QUICKSORT的时间复杂度为
。
7.2-4 银行一般会按照交易时间来记录某一账户的交易情况。但是,很多人却喜欢收到的银行对账单是按照支票号码的顺序来排列的。这是因为,人们通常都是按照支票号码的顺序来开出支票的,而商人也通常都是根据支票编号的顺序兑付支票。这一问题是将按交易时间排序的序列转换成按支票号排序的序列,它实质上是一个对几乎有序的输入序列进行排序的问题。请证明:在这个问题上,INSERTION-SORT的性能往往要优于QUICKSORT。
解
根据前面的分析,对于一个几乎有序的数组,插入排序接近它的最好情况,时间复杂度接近
。而快速排序接近它的最坏情况,时间复杂度接近
。所以插入排序的性能要优于快速排序。
7.2-5 假设快速排序的每一层所做的划分的比例都是
,其中
且是一个常数。试证明:在相应的递归树中,叶结点的最小深度大约是
,最大深度大约是
(无需考虑整数舍入问题)。
解
在递归树中,最小深度的叶结点出现在每次划分比例为
的分枝,即子问题规模较小的那个分枝,它的深度为
。
在递归树中,最大深度的叶结点出现在每次划分比例为
的分枝,即子问题规模较大的那个分枝,它的深度为
。
7.2-6 试证明:在一个随机输入数组上,对于任何常数
,PARTITION产生比
更平衡的划分的概率约为
。
解
对数组的划分取决于被选择的划分主元。假如数组大小为
。如果划分主元是数组中最大的
个元素中的一个,那么对数组的划分一定不会比
更平衡。如果划分主元是数组中最小的
个元素中的一个,那么对数组的划分也一定不会比
更平衡。对于数组中间的
个元素,如果划分主元是其中一个,那么产生的划分才会比
更平衡。
对于一个随机输入数组,数组中的每一个元素都有相同的概率被选为划分主元。根据前面的分析,产生比
更好的划分的概率,也等于划分主元为中间的
个元素之一的概率,这个概率为
。