1 E2 c! Z* Q' K+ A7 }首先,假设n= 1时是一个小问题,n> 1时为一个大问题。后面将根据需要随时修改这个假设。对于1×1阶的小矩阵,可以通过将两矩阵中的两个元素直接相乘而得到结果。4 s: w: i& A8 J8 L! {# D r2 b
- w$ S7 T) Y; O$ v. O考察一个n> 1的大问题。可以将这样的矩阵分成4个n/ 2×n/ 2阶的矩阵A1,A2,A3,和A4。当n 大于1且n 是2的幂时,n/ 2也是2的幂。因此较小矩阵也满足前面对矩阵大小的假设。矩阵Bi 和Ci 的定义与此类似. 0 l2 q- D q* E" L! T 8 F& g. G( y, K" \根据上述公式,经过8次n/ 2×n/ 2阶矩阵乘法和4次n/ 2×n/ 2阶矩阵的加法,就可以计算出A与B的乘积。因此,这些公式能帮助我们实现分而治之算法。在算法的第二步,将递归使用分而治之算法把8个小矩阵再细分(见程序2 - 1 9)。算法的复杂性为(n3 ),此复杂性与程序2 - 2 4直接使用公式(2 - 1)所得到的复杂性是一样的。事实上,由于矩阵分割和再组合所花费的额外开销,使用分而治之算法得出结果的时间将比用程序2 - 2 4还要长。 4 B. f4 K( c& P: ^& o - [" D' l, H0 j' ~' w4 c为了得到更快的算法,需要简化矩阵分割和再组合这两个步骤。一种方案是使用S t r a s s e n方法得到7个小矩阵。这7个小矩阵为矩阵D, E, ., J,矩阵D到J可以通过7次矩阵乘法, 6次矩阵加法,和4次矩阵减法计算得出。前述的4个小矩阵可以由矩阵D到J通过6次矩阵加法和两次矩阵减法得出. ]9 Q& o% ~3 V- V; s' Z
# n }: D+ A( c8 l用上述方案来解决n= 2的矩阵乘法。将某矩阵A和B相乘得结果C,如下所示:0 n3 ]# r( ?7 W) g
/ q1 Y. }% @' v$ ^2) 比较每个大小为2的问题中的金块,确定哪一个较重和哪一个较轻。在节点D、E、F和G上完成这种比较。大小为1的问题中只有一个金块,它既是最轻的金块也是最重的金块。( @7 K2 Y, x6 ]+ Z! O
* j0 ~, _( B) o" V7 A* K: ?
3) 对较轻的金块进行比较以确定哪一个金块最轻,对较重的金块进行比较以确定哪一个金块最重。对于节点A到C执行这种比较。# q: E% \# m3 a |) b
4 b* T1 d! [: v' r6 S& j% E% {; h
根据上述步骤,可以得出程序1 4 - 1的非递归代码。该程序用于寻找到数组w [ 0 : n - 1 ]中的最小数和最大数,若n < 1,则程序返回f a l s e,否则返回t r u e。$ d: |6 y0 _% N0 z5 k
* d; O5 Q7 C* M( ^当n≥1时,程序1 4 - 1给M i n和M a x置初值以使w [ M i n ]是最小的重量,w [ M a x ]为最大的重量。 , F1 n4 q) O- n; ~# n6 l5 h+ n# f) N$ [
首先处理n≤1的情况。若n>1且为奇数,第一个重量w [ 0 ]将成为最小值和最大值的候选值,因此将有偶数个重量值w [ 1 : n - 1 ]参与f o r循环。当n 是偶数时,首先将两个重量值放在for 循环外进行比较,较小和较大的重量值分别置为Min和Max,因此也有偶数个重量值w[2:n-1]参与for循环。. s H1 e1 `4 F5 f* q1 Q. T
J. w4 F; G8 @* O5 r- f; F& s在for 循环中,外层if 通过比较确定( w [ i ] , w [ i + 1 ] )中的较大和较小者。此工作与前面提到的分而治之算法步骤中的2) 相对应,而内层的i f负责找出较小重量值和较大重量值中的最小值和 , {1 _% B0 e/ u4 ]/ Q ; G; P0 i) Q3 j8 @3 ~) O最大值,这个工作对应于3 )。for 循环将每一对重量值中较小值和较大值分别与当前的最小值w [ M i n ]和最大值w [ M a x ]进行比较,根据比较结果来修改M i n和M a x(如果必要)。& \5 H3 ], ?/ k4 e6 z5 j2 a
7 P" t! H% u. l. s b `
下面进行复杂性分析。注意到当n为偶数时,在for 循环外部将执行一次比较而在f o r循环内部执行3 ( n / 2 - 1 )次比较,比较的总次数为3 n / 2 - 2。当n 为奇数时,f o r循环外部没有执行比较,而内部执行了3(n-1)/2次比较。因此无论n 为奇数或偶数,当n>0时,比较的总次数为「3n/2ù-2次。 " h$ _ J, p3 s/ o$ G3 R% G5 b! ~, q' I. W# w
程序14-1 找出最小值和最大值的非递归程序 ! M7 g9 \0 A: `9 U6 ~! p, c6 L; p% _2 R/ f
template<CLASS T>. p3 \& `) U+ B
5 y4 z! O8 Z6 P* R5 G+ X5 @ \& U
bool MinMax(T w[], int n, T& Min, T& Max) 5 l" j. y5 i- m! H$ o9 q0 A2 s" a0 k3 r0 ?9 F: n% B8 B u" y
{// 寻找w [ 0 : n - 1 ]中的最小和最大值 r# Q, _7 q( l6 s9 P & c0 m- `" J _) v: ^/ ?2 u// 如果少于一个元素,则返回f a l s e8 p, Z" ^# P/ K* n
, k' D; K9 r: X, D( Q, Z1 ]/ U
// 特殊情形: n <= 1! K- c, ^8 o% z
, x2 W4 H: C! @& ?+ mif (n < 1) return false; % i4 r( ]8 O0 ^1 l' Y$ u) w( N# b2 F1 U9 i) ]* g
if (n == 1) {Min = Max = 0; + B, a* |5 {' \" V( y5 z! r/ Y% U/ i$ {! E2 N7 H- T" E, x
return true;} * n$ d" T) n ^# z" v* t6 ~& s/ ~, g ]2 w1 m1 v
/ /对Min 和M a x进行初始化: \& R. `4 p4 o- `! e
5 }) N1 I9 [: n7 H/ F+ N7 B% _int s; // 循环起点 / [9 o h- \; m6 f7 t " ?9 g5 w+ D" _" h3 U! W" Oif (n % 2) {// n 为奇数1 g, p9 ]3 W6 S i1 L5 f0 P3 }! a# n
- ^1 p. O' J" p3 I6 E$ J2 S! TMin = Max = 0;/ U9 `0 g6 v+ j) v: t) D
" A& @' Q. m" L7 p! K/ p3 Ss = 1;} & Z5 m8 J5 _6 o; r* d / h( U0 G- K2 r1 \, relse {// n为偶数,比较第一对( P. J/ f0 d' S2 C2 C( r9 k! E% A
+ l9 s) D4 c- o! aif (w[0] > w[1]) {/ H" l' |9 T# R+ Z+ K1 R
( q% ~3 |; K" G( ]$ [& ]7 fMin = 1;5 |* q4 ~2 M/ |, D
( S% H, O9 i, _
Max = 0;} ) [2 n% `, E7 B/ ]* l. p; X+ K: l" g! j- M) p$ N3 g6 Y" n3 e
else {Min = 0; : Q$ z$ g0 A4 S8 J$ N+ M- B T6 @ : S/ b+ o# r' T/ d" XMax = 1;}2 Y7 w, g, y1 P& G1 w7 J% E1 U. O, A
" k2 h4 x) f; Q1 `0 l# J0 [: o2 i
s = 2;}- l9 M) a- | B0 q* b
6 P( A+ A1 y3 i& S- Z
// 比较余下的数对 ) H9 D" t8 ?& x2 d& s+ N$ h: o p( g8 h7 U
for (int i = s; i < n; i += 2) {& |2 \) a) Z/ p0 e# }2 b6 i
3 \6 W! Z+ N( q; x* D0 D' z# d
// 寻找w 和w [ i + 1 ]中的较大者& Z' z3 |: S k2 N( @5 K
9 k0 p2 Y% N5 q. p4 D% R1 o9 P
// 然后将较大者与w [ M a x ]进行比较 9 X) k$ q! {8 Y* s- N 6 n. H$ X, D* ~; w" i5 N% y// 将较小者与w [ M i n ]进行比较8 O1 P* N& I6 e `" f$ A3 R. O# W# M
# F/ u( c& {- S# c" C$ D* O, C; I+ E
if (w > w[i+1]) {) J& ]; c, A0 v4 d6 ]5 K
+ c$ k5 g b$ d$ Z; J+ Z, ?0 j
if (w > w[Max]) Max = i; ; M/ e! v7 d9 a! X( [+ G ! c M3 {# ?" z" q& I& iif (w[i+1] < w[Min]) Min = i + 1;}- d8 X# [! a1 X- g4 Y
$ X/ e" J2 Y. m% S
else { 3 U2 r5 W2 v. b' C- f) [ 0 O. ^4 i& W8 ^( r' t7 ^/ e) x3 Aif (w[i+1] > w[Max]) Max = i + 1; 6 e& V+ N9 U# |& M, \* L3 K 3 k8 B0 ~ c$ a8 j+ Yif (w < w[Min]) Min = i;} 3 Q/ m' l$ m; L& [. T% m! {7 c) i* U" z" I; E# K1 Z
}0 g4 p& i* d6 H8 a
( n0 [/ T. D/ M: z& u% T4 C, C
return true;1 }1 V, o5 W( B- a8 f c! s8 W
, Z6 s, r0 l: R- u; ~
} 3 v2 N* @, I# i0 C' R / x6 O9 q# {$ g4 |# e练习 7 N9 T! E' g) { o$ C" A: H9 B! D5 ^; F! a. B) ]" I$ Q! M
1. 将例1 4 - 1的分而治之算法扩充到n> 1个硬币的情形。需要进行多少次重量的比较? / p, w l$ Z0 l0 j/ `# i9 @ [2 X8 z0 [9 i( K2. 考虑例1 4 - 1的伪币问题。假设把条件“伪币比真币轻”改为“伪币与真币的重量不同”,同样假定袋中有n 个硬币。' W/ U3 P: ]6 Y1 a% k* d- F
, F+ d* {% N* Y2 _2 S' }
1) 给出相应分而治之算法的形式化描述,该算法可输出信息“不存在伪币”或找出伪币。算法应递归地将大的问题划分成两个较小的问题。需要多少次比较才能找到伪币(如果存在伪币)?& _# X- ^4 T& B6 M. k
* c$ X# K# _5 r2 W9 D
2) 重复1) ,但把大问题划分为三个较小问题。7 S7 a) @, Z' L1 C
9 c: J. a$ F/ K; n' a' j- V8 _; Y% J3. 1) 编写一个C++ 程序,实现例1 4 - 2中寻找n 个元素中最大值和最小值的两种方案。使用递归来完成分而治之方案。+ k4 S) m. ]7 }