我一直在阅读描述如何通过使用尾递归版本来降低快速排序的空间复杂度的文章,但我无法理解这是怎么回事。以下是两个版本:
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)
据我了解,这两者都会导致数组的左半部分和右半部分递归调用。在这两种情况下,一次只会处理一半,因此在任何时候只有一个递归调用会使用堆栈空间。我无法看到尾递归快速排序如何节省空间。
上面的伪代码摘自文章 -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文章中的解释更让我困惑——
快速排序对给定的子数组进行分区并继续递归两次;
一个在左侧子数组,一个在右侧。这些中的每一个
递归调用将需要其自己的单独的堆栈空间流。
该空间用于存储数组的索引变量
某种程度的递归。如果我们从一开始就想象这种情况发生
到执行结束时,我们可以看到堆栈空间每次都会翻倍
层。
那么尾递归快速排序如何解决所有这些问题呢?
好吧,我们现在只递归两个子数组,而不是递归
一。这样就无需在每一层将堆栈空间加倍
的执行。我们通过使用 while 循环来解决这个问题
执行相同任务的迭代控制。而不是需要
堆栈来保存两个递归调用的变量集,我们只需
更改同一组变量并使用单个递归调用
新变量。
我不明白在常规快速排序的情况下,堆栈空间如何在每一层执行时加倍。
注意:- 本文中没有提及编译器优化。