笔记
快速排序采用了分治的思想。对于一个数组
A
[
p
.
.
r
]
A[p..r]
A[p..r],调用一个PARTITION过程,将它划分为两部分
A
[
p
.
.
q
−
1
]
A[p..q-1]
A[p..q−1]和
A
[
q
+
1..
r
]
A[q+1..r]
A[q+1..r],使得
A
[
p
.
.
q
−
1
]
A[p..q-1]
A[p..q−1]中的每一个元素都不大于
A
[
q
]
A[q]
A[q],而
A
[
q
+
1..
r
]
A[q+1..r]
A[q+1..r]中的每一个元素都不小于
A
[
q
]
A[q]
A[q]。并且将
A
[
q
]
A[q]
A[q]置于
A
[
p
.
.
q
−
1
]
A[p..q-1]
A[p..q−1]和
A
[
q
+
1..
r
]
A[q+1..r]
A[q+1..r]的中间,这样
A
[
q
]
A[q]
A[q]就已经处于正确的排序位置上了。然后分别对
A
[
p
.
.
q
−
1
]
A[p..q-1]
A[p..q−1]和
A
[
q
+
1..
r
]
A[q+1..r]
A[q+1..r]递归执行以上过程。下面的伪代码展示了这一过程。
快速排序的关键在于PARTITION过程,如下所示。
上述这个
P
A
R
T
I
T
I
O
N
(
A
,
p
,
r
)
{\rm PARTITION}(A, p, r)
PARTITION(A,p,r)过程结束之后,数组
A
[
p
.
.
r
]
A[p..r]
A[p..r]满足:
A
[
p
.
.
q
−
1
]
A[p..q-1]
A[p..q−1]中的元素都小于或等于
A
[
q
]
A[q]
A[q],
A
[
q
+
1..
r
]
A[q+1..r]
A[q+1..r]中的元素都严格大于
A
[
q
]
A[q]
A[q]。下图展示了一个PARTITION的例子。
PARTITION在数组
A
[
p
.
.
r
]
A[p..r]
A[p..r]上的时间复杂度为
Θ
(
n
)
Θ(n)
Θ(n),其中
n
n
n为数组长度,即
n
=
r
−
p
+
1
n = r-p+1
n=r−p+1。
练习
7.1-1 参照图7-1的方法,说明PARTITION在数组A = {13, 19, 9, 5, 12, 8, 7, 4, 21, 2, 6, 11}上的操作过程。
解
7.1-2 当数组
A
[
p
.
.
r
]
A[p..r]
A[p..r]中的元素都相同时,PARTITION返回的
q
q
q值是什么?修改PARTITION,使得当数组
A
[
p
.
.
r
]
A[p..r]
A[p..r]中所有元素的值都相同时,
q
=
⌊
(
p
+
r
)
/
2
⌋
q=⌊(p+r)/2⌋
q=⌊(p+r)/2⌋。
解
当数组中的元素都相同时,PARTITION返回
q
=
r
q = r
q=r。
当数组中所有元素都相同时,要使得返回
q
=
⌊
(
p
+
r
)
/
2
⌋
q=⌊(p+r)/2⌋
q=⌊(p+r)/2⌋,最简单的办法是在代码中检查这种情况。如果检查到这种情况,直接返回
q
=
⌊
(
p
+
r
)
/
2
⌋
q=⌊(p+r)/2⌋
q=⌊(p+r)/2⌋即可。而检查数组中所有元素是否相同,所花费的时间为
Θ
(
n
)
Θ(n)
Θ(n),并不会改变PARTITION的时间复杂度。
7.1-3 请简要地证明:在规模为
n
n
n的子数组中,PARTITION的时间复杂度为
Θ
(
n
)
Θ(n)
Θ(n)。
略
7.1-4 如何修改QUICKSORT,使得它能够以非递增序进行排序。
解
只需要修改PARTITION过程即可。
本节code链接:https://github.com/yangtzhou2012/Introduction_to_Algorithms_3rd/tree/master/Chapter07/Section_7.1