查看以下尾部递归quicksort伪代码
QuickSort(A[1, ..., n], lo, hi)
Input: An array A of n distinct integers, the lower index and the higher index
// For the first call lo = 1 and hi = n
Output: The array A in sorted order
If lo = hi return
// The array A is already sorted in this case
If lo > hi or indices out of the range 1 to n then return
Else
Pick an index k in [lo,hi] as the pivot
// Assume that this can be done using O(1) cells on the stack
i = Partition(A[lo, ..., hi], k)
// Use in-place partitioning here so assume that this can be done
// using O(1) space on the stack
If i - lo <= hi - i
QuickSort(A, lo, i-1) // sort the smaller half first
QuickSort(A, i+1, hi)
Else
QuickSort(A, i+1, hi) // sort the smaller half first
QuickSort(A, lo, i-1)
假设我每次分析枢轴时都经过对抗性选择,那么它的空间复杂度应为O(logn)[我不确定是完全正确的],但是如果枢轴为零,那么空间复杂度将受到怎样的影响随机选择统一?我对了解空间复杂度而不是时间复杂度还很陌生,因此感谢您提供任何反馈意见!
答案 0 :(得分:0)
请参阅这篇涵盖Tail Recursion
的文章在文章中,它表示尾递归快速排序的空间复杂度如下:
space complexity = input + O(log(n))
可以在下面找到一些更深入了解的文章:
答案 1 :(得分:0)
时间的最坏情况是,如果将数组划分得尽可能不均匀,那么该时间将为O(n^2)
。如果您不执行尾递归,那对于空间来说也是最糟糕的情况。
但是,如果您不均匀地划分数组并进行尾递归排序,则对较大的一半进行排序的调用不会占用任何空间,因为您只需替换当前的调用框架即可。因此,使用的最大空间是当您一次又一次地进行第一次递归调用时。在最多1/2
个呼叫帧中,最多... 1/2
个中的log_2(n)
个。
如果使用统一选择的枢轴从最坏情况切换到一般情况,则再次为O(log(n))
,但常数更好。首先,它不能超过此范围,因为平均情况不能超过最坏情况。
诀窍是证明您无法提高界限。为了证明这一点,我们可以证明对大小为n
的数组进行排序的平均空间至少为C log(n+1)/(3 log(2))
,其中C
是单个调用的空间。
通过检查,对于n = 1, 2, ..., 7
来说确实如此,因为初始调用占用了空间C
和log(n+1)/(3 log(2)) <= 1
。
如果n
大于7,并且对n
为止的语句都是正确的,则我们的透视图会将我们分成大小为m
和n-m
的组,其中{{1 }}。至少有m <= n-m
的赔率,而且我们在第一个递归调用中的预期最高费用至少为
n <= 4m
剩余的剩余时间和我们在尾部递归调用中的预期最大费用至少为
C 1 + f(m)
>= C + f(n/4 rounded up)
>= C (3 log(2)) /(3 log(2)) + C log(n/4 + 1)/(3 log(2)))
> C (3 log(2) + log(n+1) - 2 log(2) ) / (3 log(2)) )
= C (log(n+1) + log(2)) / (3 log(2))
将这两个值取平均值时,将得到所需的f(n-m)
>= f(n/2 rounded down)
>= C log(n/2 + 1/2) / (3 log(2)) # n/2
= C (log(n+1) - log(2)) / (3 log(2))
下限。
(我可能犯了一个小错误,但是这个想法是正确的。)