算法导论 — 7.2 快速排序的性能

笔记

本节只给出快速排序运行时间的简单分析。快速排序的运行时间取决于PARTITION划分是否平衡,而划分的平衡与否又取决于用于划分的主元的选择。
  1. 最坏情况时间复杂度
  对于一个含 n n 个元素的数组,PARTITION划分的最坏情况为:划分产生的两个子数组的大小分别为 n 1 n-1 0 0 时。假设快速排序每一次递归调用PARTITION都产生了最坏情况划分,那么算法的运行时间 T ( n ) T(n) 满足以下递归式。
   T ( n ) = T ( n 1 ) + T ( 0 ) + Θ ( n ) = T ( n 1 ) + Θ ( n ) T(n) = T(n-1) + T(0) + Θ(n) = T(n-1) + Θ(n)
  求解这个递归式得到 T ( n ) = Θ ( n 2 ) T(n) = Θ(n^2) 。也就是说,如果快速排序的每一次递归调用都产生了最坏情况划分,那么算法的时间复杂度为 Θ ( n 2 ) Θ(n^2)
  快速排序最坏情况的一个例子是,输入数组已经完全有序,此时快速排序的时间复杂度为 Θ ( n 2 ) Θ(n^2) 。而同样的情况下,如果采用插入排序,时间复杂度为 Θ ( n ) Θ(n) 。因此,在数组已经有序的时候,插入排序要优于快速排序。
  2. 最好情况时间复杂度
  快速排序的最好情况出现在:每一次PARTITION都得到一个完全平衡的划分,即对于一个含 n n 个元素的数组,PARTITION产生的两个子数组的大小分别为 ( n 1 ) / 2 ⌊(n-1)/2⌋ ( n 1 ) / 2 ⌈(n-1)/2⌉ 。假设快速排序每一次递归调用都产生了最好情况划分,那么算法的运行时间 T ( n ) T(n) 满足以下递归式。
   T ( n ) = 2 T ( n / 2 ) + Θ ( n ) T(n) = 2T(n/2) +Θ(n)
  求解这个递归式得到 T ( n ) = Θ ( n l g n ) T(n) = Θ(nlgn) ,这就是快速排序最好情况的时间复杂度。
  3. 平均情况的时间复杂度
  本节给出了结论:快速排序的平均情况时间复杂度为 Θ ( n l g n ) Θ(n{\rm lg}n) 。本节对这一结论只做了简要的说明,在7.4节会给出严格的证明,我们先记下这个结论。

练习

7.2-1 利用代入法证明:正如7.2节开头提到的那样,递归式 T ( n ) = T ( n 1 ) + Θ ( n ) T(n) = T(n-1) + Θ(n) 的解为 T ( n ) = Θ ( n 2 ) T(n) = Θ(n^2)
  
  
  
7.2-2 当数组 A A 的所有元素都具有相同的值时,QUICKSORT的时间复杂度是什么?
  
  利用练习7.1-2的结论,当所有元素都相同时,每次调用PARTITION都产生一个最坏情况划分,因此这种情况下,QUICKSORT的时间复杂度为 Θ ( n 2 ) Θ(n^2)
  
  
7.2-3 证明:当数组 A A 包含的元素各不相同,并且是按降序排列的时候,QUICKSORT的时间复杂度为 Θ ( n 2 ) Θ(n^2)
  
  考虑包含 n n 个元素的数组 A A ,其中元素各不相同,并且按降序排列,即 a 1 > a 2 > > a n a_1 > a_2 > … > a_n 。我们来分析每次调用PARTITION的情况。
  在这里插入图片描述
  第 1 1 次划分,调用 P A R T I T I O N ( A , 1 , n ) {\rm PARTITION}(A, 1, n) ,由于被选为划分主元的 a n a_n 是最小的,所以最终 a 1 a_1 a n a_n 交换,产生最坏情况划分。
  第 2 2 次划分,调用 P A R T I T I O N ( A , 2 , n ) {\rm PARTITION}(A, 2, n) ,由于被选为划分主元的 a 1 a_1 是最大的,所以这次划分没有任何改变,也是一个最坏情况划分。
  接下来的第 3 3 次划分,调用 P A R T I T I O N ( A , 2 , n 1 ) {\rm PARTITION}(A, 2, n-1) ,此时数组 A [ 2.. n 1 ] A[2..n-1] 又是一个降序排列的数组,因此也产生一个最坏情况划分。
  如此循环往复下去,每次调用 P A R T I T I O N {\rm PARTITION} 都产生一个最坏情况划分。所以数组按降序排列的情况下,QUICKSORT的时间复杂度为 Θ ( n 2 ) Θ(n^2)
  
  
7.2-4 银行一般会按照交易时间来记录某一账户的交易情况。但是,很多人却喜欢收到的银行对账单是按照支票号码的顺序来排列的。这是因为,人们通常都是按照支票号码的顺序来开出支票的,而商人也通常都是根据支票编号的顺序兑付支票。这一问题是将按交易时间排序的序列转换成按支票号排序的序列,它实质上是一个对几乎有序的输入序列进行排序的问题。请证明:在这个问题上,INSERTION-SORT的性能往往要优于QUICKSORT。
  
  根据前面的分析,对于一个几乎有序的数组,插入排序接近它的最好情况,时间复杂度接近 Θ ( n ) Θ(n) 。而快速排序接近它的最坏情况,时间复杂度接近 Θ ( n 2 ) Θ(n^2) 。所以插入排序的性能要优于快速排序。
  
  
7.2-5 假设快速排序的每一层所做的划分的比例都是 1 α α 1-α:α ,其中 0 < α 1 / 2 0 < α ≤ 1/2 且是一个常数。试证明:在相应的递归树中,叶结点的最小深度大约是 l g n / l g α {\rm lg}n/{\rm lg}α ,最大深度大约是 l g n / l g ( 1 α ) {\rm lg}n/{\rm lg}(1-α) (无需考虑整数舍入问题)。
  
  在递归树中,最小深度的叶结点出现在每次划分比例为 α α 的分枝,即子问题规模较小的那个分枝,它的深度为 l o g α n = l g n / l g α {\rm log}_αn = {\rm lg}n/{\rm lg}α
  在递归树中,最大深度的叶结点出现在每次划分比例为 1 α 1-α 的分枝,即子问题规模较大的那个分枝,它的深度为 l o g 1 α n = l g n / l g ( 1 α ) {\rm log}_{1-α}n = {\rm lg}n/{\rm lg}(1-α)
  
  
7.2-6 试证明:在一个随机输入数组上,对于任何常数 0 < α 1 / 2 0 < α ≤ 1/2 ,PARTITION产生比 1 α α 1-α:α 更平衡的划分的概率约为 1 2 α 1-2α
  
  对数组的划分取决于被选择的划分主元。假如数组大小为 n n 。如果划分主元是数组中最大的 α n αn 个元素中的一个,那么对数组的划分一定不会比 1 α α 1-α:α 更平衡。如果划分主元是数组中最小的 α n αn 个元素中的一个,那么对数组的划分也一定不会比 1 α α 1-α:α 更平衡。对于数组中间的 n 2 α n n-2αn 个元素,如果划分主元是其中一个,那么产生的划分才会比 1 α α 1-α:α 更平衡。
  对于一个随机输入数组,数组中的每一个元素都有相同的概率被选为划分主元。根据前面的分析,产生比 1 α α 1-α:α 更好的划分的概率,也等于划分主元为中间的 n 2 α n n-2αn 个元素之一的概率,这个概率为 ( n 2 α n ) / n = 1 2 α (n-2αn)/n = 1-2α

猜你喜欢

转载自blog.csdn.net/yangtzhou/article/details/85010662
今日推荐