- F6 ^7 d5 ]( H* ~+ C& M为了得到更快的算法,需要简化矩阵分割和再组合这两个步骤。一种方案是使用S t r a s s e n方法得到7个小矩阵。这7个小矩阵为矩阵D, E, ., J,矩阵D到J可以通过7次矩阵乘法, 6次矩阵加法,和4次矩阵减法计算得出。前述的4个小矩阵可以由矩阵D到J通过6次矩阵加法和两次矩阵减法得出. 6 ~/ r, X3 E8 ~% E+ @; y/ n) E$ T- I; Z; q/ u" W
用上述方案来解决n= 2的矩阵乘法。将某矩阵A和B相乘得结果C,如下所示:$ O5 @! ~: V3 H; @% E# J6 Y. F
2 `2 s C: c3 W0 N; P1 X* Y因为n> 1,所以将A、B两矩阵分别划分为4个小矩阵,每个矩阵为1×1阶,仅包含一个元素。1×1阶矩阵的乘法为小问题,因此可以直接进行运算。利用计算D~J的公式,得:5 u I% w+ U; c( y
5 p$ H) z6 h0 h# d
D= 1(6-8)=-2 + F; b8 j! t7 k9 U0 [) S% o2 o* `; h
E= 4(7-5)= 8 2 ~2 P6 M$ I ?2 R7 @4 ?/ @, |) g( }0 w; G4 g2 `
F=(3 + 4)5 = 3 5 4 k3 I. j8 k6 L) Y * d* Q, s$ L* ^* F& z3 g# ZG=(1 + 2)8 = 2 45 c6 @/ D0 z Q1 x1 [
3 C$ P! R; j0 M$ \$ B H
H=(3-1)(5 + 6)= 2 2 t8 S& r* }5 v; P
4 J0 O4 C: U0 T O对于上面这个2×2的例子,使用分而治之算法需要7次乘法和1 8次加/减法运算。而直接使用公式(2 - 1),则需要8次乘法和7次加/减法。要想使分而治之算法更快一些,则一次乘法所花费的时间必须比11次加/减法的时间要长。4 ]* g6 V2 ?1 R9 n S2 L
) _( C b. D! S1 G! |, S3 Z
假定S t r a s s e n矩阵分割方案仅用于n≥8的矩阵乘法,而对于n<8的矩阵乘法则直接利用公式(2 - 1)进行计算。则n= 8时,8×8矩阵相乘需要7次4×4矩阵乘法和1 8次4×4矩阵加/减法。每次矩阵乘法需花费6 4m+ 4 8a次操作,每次矩阵加法或减法需花费1 6a次操作。因此总的操作次数为7 ( 6 4m+ 4 8a) + 1 8 ( 1 6a) = 4 4 8m+ 6 2 4a。而使用直接计算方法,则需要5 1 2m+ 4 4 8a次操作。要使S t r a s s e n方法比直接计算方法快,至少要求5 1 2-4 4 8次乘法的开销比6 2 4-4 4 8次加/减法的开销大。或者说一次乘法的开销应该大于近似2 . 7 5次加/减法的开销。5 H: a0 ^- L, m4 O) m7 p
q4 a# q8 `' p假定n<1 6的矩阵是一个“小”问题,S t r a s s e n的分解方案仅仅用于n≥1 6的情况,对于n<1 6的矩阵相乘,直接利用公式( 2 - 1)。则当n= 1 6时使用分而治之算法需要7 ( 5 1 2m+ 4 4 8a) +1 8 ( 6 4a) = 3 5 8 4m+ 4 2 8 8a次操作。直接计算时需要4 0 9 6m+ 3 8 4 0a次操作。若一次乘法的开销与一次加/减法的开销相同,则S t r a s s e n方法需要7 8 7 2次操作及用于问题分解的额外时间,而直接计算方法则需要7 9 3 6次操作加上程序中执行f o r循环以及其他语句所花费的时间。即使直接计算方法所需要的操作次数比St r a s s e n方法少,但由于直接计算方法需要更多的额外开销,因此它也不见得会比S t r a s s e n方法快。9 A9 d: E0 {) T2 v9 h# u
5 V3 c, g& a% M$ ?- u( j3) 对较轻的金块进行比较以确定哪一个金块最轻,对较重的金块进行比较以确定哪一个金块最重。对于节点A到C执行这种比较。 9 \. P; B+ Z9 b3 l) y% j 7 [- j7 \3 S7 h% }根据上述步骤,可以得出程序1 4 - 1的非递归代码。该程序用于寻找到数组w [ 0 : n - 1 ]中的最小数和最大数,若n < 1,则程序返回f a l s e,否则返回t r u e。 0 p) r- E; V+ i7 F$ f. G+ J" W6 i. i9 S. R* v- z) B
当n≥1时,程序1 4 - 1给M i n和M a x置初值以使w [ M i n ]是最小的重量,w [ M a x ]为最大的重量。 3 a: M9 ~. U7 b) w# ~' j% C7 [ e8 w) E0 m b. }
首先处理n≤1的情况。若n>1且为奇数,第一个重量w [ 0 ]将成为最小值和最大值的候选值,因此将有偶数个重量值w [ 1 : n - 1 ]参与f o r循环。当n 是偶数时,首先将两个重量值放在for 循环外进行比较,较小和较大的重量值分别置为Min和Max,因此也有偶数个重量值w[2:n-1]参与for循环。: t( S+ {) s2 [0 u0 u# @& h6 v4 ~" |3 H
6 ^1 |: f/ c f在for 循环中,外层if 通过比较确定( w [ i ] , w [ i + 1 ] )中的较大和较小者。此工作与前面提到的分而治之算法步骤中的2) 相对应,而内层的i f负责找出较小重量值和较大重量值中的最小值和 ' M, d8 g- L. }* ]7 G( n, E- W3 F& A + o2 n4 b$ ]: M" }最大值,这个工作对应于3 )。for 循环将每一对重量值中较小值和较大值分别与当前的最小值w [ M i n ]和最大值w [ M a x ]进行比较,根据比较结果来修改M i n和M a x(如果必要)。 " G! ^3 l5 y' U3 J7 ~' O4 |7 R- _+ R' l' N' ^1 G( y) h
下面进行复杂性分析。注意到当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次。 ' U5 F. Y+ z6 t0 _# Z6 Y6 [+ [ / S8 J2 _2 g3 L R/ t程序14-1 找出最小值和最大值的非递归程序/ s+ L1 }' s' M# J/ B. ^
; _! Y; a2 L! i+ R
template<CLASS T> , b+ L, L2 Q$ z# ~+ o1 ] / [7 a" p4 ^ B! mbool MinMax(T w[], int n, T& Min, T& Max)- B. I* S! ~: \) o' N% T. G5 G
4 O4 v4 V. n$ m+ r, I n{// 寻找w [ 0 : n - 1 ]中的最小和最大值 : j" q" b: q. N% W8 s6 K8 e0 X h1 \9 a5 T ~' H6 {$ D% ^
// 如果少于一个元素,则返回f a l s e) E" y; S! c a3 d, R7 k7 m
" L F) ]( K: m. h y4 N
// 特殊情形: n <= 1 ( B9 l; |8 T1 w, y0 U. M+ i" s/ v/ S+ W5 h8 c: i2 o
if (n < 1) return false;% Z" O0 D# I5 k# y! Q
4 ]7 c8 f$ @& u, ~$ Nif (n == 1) {Min = Max = 0; 5 Z: o: u, @+ q5 G * H* c$ B$ f1 B% y f3 ureturn true;} 8 K' u v* }( r2 s& p! W4 m0 j 0 z: j( |& D* S. D) {9 q' t& T0 ^$ V6 x2 u/ /对Min 和M a x进行初始化1 a; e" h# C" e5 n6 S& I
$ S5 O- Q* i) S- A7 L
int s; // 循环起点 7 h7 ~$ x! ~) O$ P0 |8 i 1 Y, Y( h$ h$ H6 \8 K6 `if (n % 2) {// n 为奇数 6 y/ p1 u% o0 M3 ?: L1 b- v l7 S! L8 d/ R% F D* J4 m* M3 bMin = Max = 0;" b: Z9 z0 ^ P" }6 H
) ^1 ]. u7 A( ^: `# y// 比较余下的数对& m7 i, \) n5 S: }
4 b+ S* c8 ]+ v7 X) o
for (int i = s; i < n; i += 2) { $ N* {# M& @+ I8 J4 p$ q/ y ! a( E+ Y' U( C- t7 j5 d// 寻找w 和w [ i + 1 ]中的较大者 l5 e! Y( a* s3 j4 X6 W
$ Q' i3 A) K2 s// 然后将较大者与w [ M a x ]进行比较" i) |0 D3 C/ {* |: G% p" j
) U& y( A! E) E3 S
// 将较小者与w [ M i n ]进行比较 : J# Z$ y2 K7 i+ g' ~3 U9 K8 t6 W6 V# W* e8 m7 `) x1 Y
if (w > w[i+1]) { : m9 p, X6 x5 k8 ^4 C5 N# W 2 U' F8 _4 n: T& lif (w > w[Max]) Max = i; ! G4 Y% g5 k9 |8 i, j# n4 _. E: c6 U% P; x, Y: p
if (w[i+1] < w[Min]) Min = i + 1;} 9 b% f6 h: x/ N/ s6 V! Y- s + v$ Y/ S H: M, I5 ~7 Selse {: U q) J( w9 ?, S& O* v7 D) e
3 x. z7 {. b) ]- t3 q: aif (w[i+1] > w[Max]) Max = i + 1;2 Z! S7 v+ A E. { P# V. g& t7 C
+ G" o5 l% _ W8 A+ \& e/ B
if (w < w[Min]) Min = i;} / L' N6 W2 ~4 V# ~0 A0 e g6 m* q9 G, L. m& W: E/ J' x
}0 N* x8 U* j& m; ]4 L: }