我一直在阅读描述如何通过使用尾递归版本来降低快速排序的空间复杂度的文章,但我无法理解这是怎么回事。以下是两个版本:
QUICKSORT(A, p, r)
q = PARTITION(A, p, r)
QUICKSORT(A, p, q-1)
QUICKSORT(A, q+1, r)
TAIL-RECURSIVE-QUICKSORT(A, p, r)
while p < r
q = PARTITION(A, p, r)
TAIL-RECURSIVE-QUICKSORT(A, p, q-1)
p = q+1
(来源 - http://mypathtothe4.blogspot.com/2013/02/lesson-2-variations-on-quicksort-tail.html)
据我了解,这两种方法都会在数组的左半边和右半边引起递归调用。在这两种情况下,一次只处理一半,因此在任何时候只有一个递归调用会使用堆栈空间。我看不到尾递归快速排序如何节省空间。
上面的伪代码取自文章——http: //mypathtothe4.blogspot.com/2013/02/lesson-2-variations-on-quicksort-tail.html 文章中提供的解释让我更加困惑——
快速排序对给定的子数组进行分区并继续递归两次;一个在左侧子阵列,一个在右侧。这些递归调用中的每一个都将需要其自己的堆栈空间流。此空间用于以某种递归级别存储数组的索引变量。如果我们想象从执行开始到结束都发生这种情况,我们可以看到堆栈空间在每一层都翻了一番。
那么 Tail-Recursive-Quicksort 如何解决所有这些问题呢?
好吧,我们现在只递归一个,而不是递归两个子数组。这消除了在每一层执行时将堆栈空间加倍的需要。我们通过使用 while 循环作为执行相同任务的迭代控制来解决这个问题。我们不需要堆栈来保存两个递归调用的变量集,我们只需更改相同的变量集并对新变量使用单个递归调用。
在常规快速排序的情况下,我看不到堆栈空间如何在每一层执行中翻倍。
注意:- 文章中没有提到编译器优化。