第二章内容:
1.一个重要概念: loop invariant.
2.规范化伪代码.
3.复合数据一般组合成对象,由attribute或field组成.
4.数组的属性:
一般取名:A或大写字母
length[A]:A的长度
5.空指针用符号
N
I
L
NIL
NIL表示v.
6.
a
n
d
/
o
r
and/or
and/or短路.
7.基于RAM和种种假设的算法分析.
8.常用设计策略:incremental和divide-and-conquer.
练习:
2.1.1:
begin-->
key:31
A:<31,41,59,26,41,58>
-->
key:41
A:<31,41,59,26,41,58>
-->
key:59
A:<31,41,59,26,41,58>
-->
key:26
A:<31,31,41,59,41,58>
->
key:26
A:<26,31,41,59,41,58>
-->
key:41
A:<26,31,41,59,59,58>
->
key:41
A:<26,31,41(1),41(2),59,58>
-->
key:59
A:<26,31,41(1),41(2),59,58>
-->
key:58
A:<26,31,41(1),41(2),59,59>
->
key:58
A:<26,31,41(1),41(2),58,59>
-->end
2.1.2.
INSERTION-SORT(A)
for j ← 2 to length[A]
do key ← A[j]
i ← j-1
while i > 0 and A[i] < key
do A[i+1] ← A[i]
i ← i-1
A[i+1] ←key
//事实上传入比较函数后:
INSERTION-SORT(A,compare())
for j ← 2 to length[A]
do key ← A[j]
i ← j-1
while i > 0 and compare(A[i],key) > 0
do A[i+1] ← A[i]
i ← i-1
A[i+1] ← key
2.1.3.
LINEAR-SEARCH(A,key)
for j ← 1 to length[A]
if key = A[j]
then return j
return NIL
初始化.很明显
A
[
0
]
A[0]
A[0]不可能为所求下标.
保持.每轮循环结束保持
k
e
y
≠
A
[
j
]
key \neq A[j]
key̸=A[j].
终止.
j
>
l
e
n
g
t
h
[
A
]
j>length[A]
j>length[A]时循环结束,但这证明A中不包括key,应该返回NIL.
2.1.4:
形式化描述:
C
[
i
]
=
A
[
i
]
+
B
[
i
]
+
f
C[i]=A[i]+B[i]+f
C[i]=A[i]+B[i]+f,其中f为进位
ADD(A,B)
f ← 0
for j ← 1 to length[A]
C[j] ← A[j] + B[j] + f
f ← C[j] ÷ 10
C[j] ← C[j] % 10
C[length[A]+1] ← f
2.2.1:
f
(
n
)
=
Θ
(
n
3
)
f(n)=\Theta(n^3)
f(n)=Θ(n3)
2.2.2:
循环不变式是:
设
A
[
0...
j
−
1
]
A[0...j-1]
A[0...j−1]是已排数组
A
[
j
.
.
.
n
]
A[j...n]
A[j...n]是待排数组
开始:
A
[
0
]
A[0]
A[0]显然是正确的排序
保持:
A
[
0...
j
−
1
]
A[0...j-1]
A[0...j−1]是已排数组,而
A
[
j
]
A[j]
A[j]被第j小数交换,这就使得
A
[
j
]
A[j]
A[j]大于等于
A
[
0...
j
−
1
]
A[0...j-1]
A[0...j−1]的所有数,小于等于
A
[
j
+
1...
n
]
A[j+1...n]
A[j+1...n]的所有数
终止:j=n-1时循环结束,事实上A[n]是第n小数,A[1…n-1]和A[n]组成给定A的所求排列。
2.2.3:
对于长度为n的数组设置第n+1的虚拟键(not found),待求key落入每个节点的可能性为
1
n
+
1
\frac{1}{n+1}
n+11,所以单论循环体的运行
f
1
(
n
)
=
1
n
+
1
+
2
n
+
1
+
.
.
.
+
n
n
+
1
=
n
2
f_1(n)=\frac{1}{n+1}+\frac{2}{n+1}+...+\frac{n}{n+1}=\frac{n}{2}
f1(n)=n+11+n+12+...+n+1n=2n,最坏情况是查找n次,
f
2
(
n
)
=
n
n
+
1
f_2(n)=\frac{n}{n+1}
f2(n)=n+1n,两种
Θ
\Theta
Θ表示均为
Θ
(
n
)
\Theta(n)
Θ(n)
2.2.4:
使之变为碰运气的算法(有可能一发即中),而不是谨慎的算法。
2.3.1:
begin-->
A:<3,41,52,26,38,57,9,49>
-->
A:<<3,41,52,26>,<38,57,9,49>>
-->
A:<<<3,41>,<52,26>>,<<38,57>,<9,49>>>
-->
A:<<<<3>,<41>>,<<52>,<26>>>,<<<38>,<57>>,<<9>,<49>>>>
-->
A:<<<3,41>,<26,52>>,<<38,57>,<9,49>>>
-->
A:<<3,26,41,52>,<9,38,49,57>>
-->
A:<3,9,26,38,41,49,52,57>
-->end
2.3.2:
MERGE(A,p,q,r)
n1 ← q-p+1
n2 ← r-q
create arrays L[1...n1] and R[1...n2]
for i ← to n1
do L[i] ← A[p+i-1]
for i ← to n2
do R[i] ← A[q+i]
cur1 ← p
cur2 ← q+1
cur ← 1
while cur1 <= n1 and cur2 <= n2
do if L[cur1]<=R[cur2]
then A[cur] ← L[cur1]
cur1 ← cur1 + 1
else A[cur] ← R[cur2]
cur2 ← cur2 + 1
cur ← cur + 1
while cur1 <= n1
do A[cur] ← L[cur1]
cur1 ← cur1 + 1
cur ← cur + 1
while cur2 <= n2
do A[cur] ← L[cur2]
cur2 ← cur2 + 1
cur ← cur + 1
2.3.3:
①
n
=
1
n=1
n=1时
T
(
2
1
)
=
2
∗
l
g
2
=
2
T(2^1)=2*lg2=2
T(21)=2∗lg2=2成立
②设
n
=
k
n=k
n=k时有
T
(
2
k
)
=
2
k
l
g
2
k
=
k
2
k
T(2^k)=2^klg2^k=k2^k
T(2k)=2klg2k=k2k,则
n
=
k
+
1
n=k+1
n=k+1时
T
(
2
k
+
1
)
=
2
T
(
2
k
+
1
/
2
)
+
2
k
+
1
=
k
2
k
+
1
+
2
k
+
1
=
(
k
+
1
)
2
k
+
1
T(2^{k+1})=2T(2^{k+1}/2)+2^{k+1}=k2^{k+1}+2^{k+1}=(k+1)2^{k+1}
T(2k+1)=2T(2k+1/2)+2k+1=k2k+1+2k+1=(k+1)2k+1也成立
③由①和②及第一数学归纳法得
T
(
n
)
=
n
l
g
n
T(n)=nlgn
T(n)=nlgn,n为2的整数次幂
2.3.4
T
(
n
)
=
{
1
,
n
=
1
T
(
n
−
1
)
+
1
,
n
>
1
T(n)=\left\{ \begin{aligned} &1 && ,n=1 \\ &T(n-1)+1 && ,n>1\\ \end{aligned} \right.
T(n)={1T(n−1)+1,n=1,n>1
2.3.5
BIN_SEARCH(A,v)
l ← 1
r ← length[A]
while r >= l
m ← (l+r)/2
do if A[m] = v
then return m
else if A[m] < v
then r = m-1
else l = m+1
return NIL
复杂度分析用搜索树说明即可
2.3.6
可以,因为A[1…j-1]是有序的。
2.3.7
先排序集合复杂度为
Θ
(
n
l
g
n
)
\Theta(nlgn)
Θ(nlgn),对于
S
S
S中的每一个
S
[
j
]
<
=
x
/
2
S[j]<=x/2
S[j]<=x/2在S[j+1…n]中寻找S[i]=x-S[j],复杂度为
Θ
(
n
l
g
n
)
\Theta(nlgn)
Θ(nlgn)所以总复杂度为
Θ
(
n
l
g
n
)
\Theta(nlgn)
Θ(nlgn)
2-1:
a.证明:
T
1
(
n
,
k
)
=
n
k
O
(
k
2
)
=
O
(
n
k
)
.
T_1(n,k)=\frac{n}{k}O(k^2)=O(nk).
T1(n,k)=knO(k2)=O(nk).
b.证明:
T
2
(
n
,
k
)
=
O
(
n
)
⋅
lg
(
n
k
)
=
O
(
n
⋅
lg
(
n
k
)
)
T_2(n,k)=O(n)\cdot \lg (\frac{n}{k})=O(n\cdot \lg (\frac{n}{k}))
T2(n,k)=O(n)⋅lg(kn)=O(n⋅lg(kn))
c.证明:
首先
k
=
lg
n
k=\lg n
k=lgn即可.
其次我们希望其拥有最好的时间复杂度,那么有:
T
1
=
O
(
T
2
)
⇔
c
1
n
k
=
c
2
n
lg
n
k
⇔
k
+
lg
k
=
c
lg
n
T_1=O(T_2)\Leftrightarrow c_1nk=c_2n\lg \frac{n}{k}\Leftrightarrow k+\lg k =c\lg n
T1=O(T2)⇔c1nk=c2nlgkn⇔k+lgk=clgn
所以实践中近似选择
k
=
c
lg
n
k=c\lg n
k=clgn,会比较好.
2-2,2-3,2-4暂略。