(快速排序的栈深度)7.1节中的QUICKSORT算法包含了两个对其自身的递归调用。在调用PARTITION后,QUICKSORT分别递归调用了左边的子数组和右边的子数组。QUICKSORT中的第二个递归调用并不是必须的。我们可以用一个循环控制结构来代替它。这一技术称为尾递归,好的编译器都提供这一功能。考虑下面这个版本的快速排序,它摸拟了尾递归的情况:
a. 证明:
T
A
I
L
−
R
E
C
U
R
S
I
V
E
−
Q
U
I
C
K
S
O
R
T
(
A
,
1
,
A
.
l
e
n
g
t
h
)
{\rm TAIL-RECURSIVE-QUICKSORT}(A, 1, A.length)
TAIL−RECURSIVE−QUICKSORT(A,1,A.length)能正确地对数组
A
A
A进行排序。
编译器通常使用栈来存储递归执行过程中的相关信息,包括每一次递归调用的参数等。最新调用的信息存在栈的顶部,而第一次调用的信息存在栈的底部。当一个过程被调用时,其相关信息被压入栈中;当它结束时,其信息则被弹出。因为我们假设数组参数是用指针来指示的,所以每次过程调用只需要
O
(
1
)
O(1)
O(1)的栈空间。栈深度是在一次计算中会用到的栈空间的最大值。
b. 请描述一种场景,使得针对一个包含
n
n
n个元素数组的TAIL-RECURSIVE-QUICKSORT的栈深度是
Θ
(
n
)
Θ(n)
Θ(n)。
c. 修改TAIL-RECURSIVE-QUICKSORT的代码,使其最坏情况下栈深度是
Θ
(
l
g
n
)
Θ(lgn)
Θ(lgn),并且能够保持
O
(
n
l
g
n
)
O(n{\rm lg}n)
O(nlgn)的期望时间复杂度。
解
a.
TAIL-RECURSIVE-QUICKSORT所做的事情与QUICKSORT完全一样。
在
Q
U
I
C
K
S
O
R
T
(
A
,
p
,
r
)
{\rm QUICKSORT}(A, p, r)
QUICKSORT(A,p,r)函数中,在递归调用
Q
U
I
C
K
S
O
R
T
(
A
,
p
,
q
−
1
)
{\rm QUICKSORT}(A, p, q-1)
QUICKSORT(A,p,q−1)后,紧接着递归调用
Q
U
I
C
K
S
O
R
T
(
A
,
q
+
1
,
r
)
{\rm QUICKSORT}(A, q+1, r)
QUICKSORT(A,q+1,r)。即在确定划分子数组后,选递归排序左边的子数组,再递归排序右边的子数组。
而在
T
A
I
L
−
R
E
C
U
R
S
I
V
E
−
Q
U
I
C
K
S
O
R
T
(
A
,
p
,
r
)
{\rm TAIL-RECURSIVE-QUICKSORT}(A, p, r)
TAIL−RECURSIVE−QUICKSORT(A,p,r)函数中,在递归调用
T
A
I
L
−
R
E
C
U
R
S
I
V
E
−
Q
U
I
C
K
S
O
R
T
(
A
,
p
,
q
−
1
)
{\rm TAIL-RECURSIVE -QUICKSORT}(A, p, q-1)
TAIL−RECURSIVE−QUICKSORT(A,p,q−1),即排序左边的子数组之后,紧接着让
p
=
q
+
1
p = q+1
p=q+1,再进入下一轮迭代。在下一轮迭代中,再排序右边的子数组。
b.
每次递归调用TAIL-RECURSIVE-QUICKSORT都是针对左边的子数组。如果一个数组已经按单调递增顺序排好序,对该数组调用PARTITION后,所得到的
2
2
2个子数组中,左边的子数组规模为
n
−
1
n-1
n−1,右边的子数组规模为
0
0
0。左边规模为
n
−
1
n-1
n−1的子数组通过递归调用TAIL-RECURSIVE-QUICKSORT来排序。因此,可以得到规模为n的数组的递归栈深度为
D
(
n
)
=
D
(
n
−
1
)
+
1
D(n) = D(n-1) + 1
D(n)=D(n−1)+1,这个递归式的解为
Θ
(
n
)
Θ(n)
Θ(n)。
c.
可以考虑这样改进:每次递归调用TAIL-RECURSIVE-QUICKSORT都排序规模较小的子数组。
这个算法的最坏情况发生在每次调用PARTITION都产生一个均衡的划分。这种情况下,栈的深度可以表示为
D
(
n
)
=
D
(
n
/
2
)
+
1
D(n) = D(n/2) + 1
D(n)=D(n/2)+1,其解为
Θ
(
l
g
n
)
Θ({\rm lg}n)
Θ(lgn)。
由于这个算法实质上与QUICKSORT一致,所以它的期望时间复杂度依然为
Θ
(
n
l
g
n
)
Θ(n{\rm lg}n)
Θ(nlgn)。
代码链接:https://github.com/yangtzhou2012/Introduction_to_Algorithms_3rd/tree/master/Chapter07/Problem_7-4/TailRecursiveQuicksort
算法导论 — 思考题7-4 快速排序的栈深度
最新推荐文章于 2021-11-19 14:55:22 发布