分类目录:​​《算法设计与分析》总目录​


在​​《快速排序-[快速排序的性能]》​​​中,我们给出了在最坏情况下快速排序性能的直观分析,以及它速度比较快的原因。在本文中,我们要给出快速排序性能的更严谨的分析。我们首先从最坏情况分析开始,其方法可以用于原版和随机化版本的​​quick_sort(arr,low,high)​​​的分析,然后给出随机化版本的​​quick_sort(arr,low,high)​​的期望运行时间。

在​​《快速排序-[快速排序的性能]》​​​中,我们得到在最坏情况下,快速排序的每一层递归的时间复杂度是 Θ ( n 2 ) \Theta(n^2) Θ(n2)。我们也从直观上了解了为什么随机化版本的​​​quick_sort(arr,low,high)​​的期望运行时间是 O ( n lg ⁡ n ) O(n\lg n) O(nlgn)。

如果在递归的每一层上,​​randomized_partition(arr,low,high)​​​将任意常数比例的元素划分到一个子数组中,则算法的递归树的深度为 Θ ( log ⁡ n ) \Theta(\log n) Θ(logn),并且每一层上的工作量都是 O ( n ) O(n) O(n)。即使在最不平衡的划分情况下,会增加一些新的层次,但总的运行时间仍然保持是 O ( n log ⁡ n ) O(n\log n) O(nlogn)。要准确地分析随机化版本的​​​quick_sort(arr,low,high)​​​的期望运行时间,首先要理解划分操作是如何进行的;然后,在此基础之上,推导出期望运行时间的一个 O ( lg ⁡ n ) O(\lg n) O(lgn)的界。有了这一期望运行时间的上界,再加​​​《快速排序-[快速排序的性能]》​​中得到的最好情况界 O ( lg ⁡ n ) O(\lg n) O(lgn),我们就能得到 O ( lg ⁡ n ) O(\lg n) O(lgn)这一期望运行时间。在这里,假设待排序的元素始终是互异的。

运行时间和比较操作

原版和随机化版本的​​quick_sort(arr,low,high)​​​除了如何选择主元元素有差异以外,其他方面完全相同。因此,我们可以在讨论​​quick_sort(arr,low,high)​​​和​​partition(arr,low,high)​​​的基础上分析​​randomized_partition(arr,low,high)​​。

​quick_sort(arr,low,high)​​​的运行时间是由在​​partition(arr,low,high)​​​操作上所花费的時间浃是的。每次对​​partition(arr,low,high)​​​的调用时,都会选择一个主元元素,而且该元素不会被包含在后续的对​​quick_sort(arr,low,high)​​​的和​​partition(arr,low,high)​​​的递归调用中。因此,在快速排序算法的整个执行期间,至多只可能调用​​partition(arr,low,high)​​​操作 n n n次。调用一次 ​​​partition(arr,low,high)​​​的时间为 O ( 1 ) O(1) O(1)再加上一段循环时间这段时间与​​​partition(arr,low,high)​​​中​​for​​​循环的迭代次数成正比。这一​​for​​​循环的每一轮迭代都要进行一次比较:比较主元元素与数组​​arr​​​中另一个元素。因此,如果我们可以统计执行的总次数,就能够给出在 ​​quick_sort(arr,low,high)​​​的执行过程中,​​for​​循环所花时间的界了。

我们还可以很容易地得出:当在一个包含 n n n个元素的数组上运行​​quick_sort(arr,low,high)​​​时,假设在​​partition(arr,low,high)​​​的比较的次数为 X X X,那么​​​quick_sort(arr,low,high)​​​的运行时间为 O ( n + X ) O(n+X) O(n+X)。那么对于随机化版本的​​​quick_sort(arr,low,high)​​,它的时间复杂度为 O ( n lg ⁡ n ) O(n \lg n) O(nlgn)。