' W' @% c. P5 `; K) E9 W, v/ E假定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次加/减法的开销。1 V1 J4 X# |8 o+ J4 S, M
0 \( T/ m" ~4 ]& C假定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方法快。 \3 H7 S' a2 R7 |5 p; d$ }$ n1 V+ n
n 的值越大,Strassen 方法与直接计算方法所用的操作次数的差异就越大,因此对于足够大的n,Strassen 方法将更快。设t (n) 表示使用Strassen 分而治之方法所需的时间。因为大的矩阵会被递归地分割成小矩阵直到每个矩阵的大小小于或等于k(k至少为8,也许更大,具体值由计算机的性能决定). 用迭代方法计算,可得t(n) = (nl og27 )。因为l og27 ≈2 . 8 1,所以与直接计算方法的复杂性(n3 )相比,分而治之矩阵乘法算法有较大的改进。 2 a& Y% O/ p" M& ?. r 6 L* ]$ ]& a/ ^0 M4 \3 g注意事项/ X' H0 C& ]; s- c
0 X; ^/ i: g# w. {1) 从图2 - 2中的二叉树由根至叶的过程中把一个大问题划分成许多个小问题,小问题的大小为1或2。 * H' M' L0 D. Y2 Q' j% Z) M% W- y- B) w9 ?6 }+ v' ?0 T
2) 比较每个大小为2的问题中的金块,确定哪一个较重和哪一个较轻。在节点D、E、F和G上完成这种比较。大小为1的问题中只有一个金块,它既是最轻的金块也是最重的金块。! x1 v7 F5 y5 k1 D a
+ y+ C3 w z5 b
3) 对较轻的金块进行比较以确定哪一个金块最轻,对较重的金块进行比较以确定哪一个金块最重。对于节点A到C执行这种比较。 ' @8 M* G u0 C7 E) R) t( R6 p" m% F7 V) U) ], |6 ^+ p; F
根据上述步骤,可以得出程序1 4 - 1的非递归代码。该程序用于寻找到数组w [ 0 : n - 1 ]中的最小数和最大数,若n < 1,则程序返回f a l s e,否则返回t r u e。7 r* d8 \7 a, ?' v( H/ S: X: p( y# O
- y+ g/ A7 \& v8 A# T当n≥1时,程序1 4 - 1给M i n和M a x置初值以使w [ M i n ]是最小的重量,w [ M a x ]为最大的重量。 e6 }) R9 @. {' J% u ?, u% [2 d+ p( A" r# k+ V
首先处理n≤1的情况。若n>1且为奇数,第一个重量w [ 0 ]将成为最小值和最大值的候选值,因此将有偶数个重量值w [ 1 : n - 1 ]参与f o r循环。当n 是偶数时,首先将两个重量值放在for 循环外进行比较,较小和较大的重量值分别置为Min和Max,因此也有偶数个重量值w[2:n-1]参与for循环。1 i# `' a E! p E1 N @" C* }
5 H6 `% W9 L4 ^5 m2 h9 j+ O在for 循环中,外层if 通过比较确定( w [ i ] , w [ i + 1 ] )中的较大和较小者。此工作与前面提到的分而治之算法步骤中的2) 相对应,而内层的i f负责找出较小重量值和较大重量值中的最小值和. y( ~" f5 j% l. R+ J+ h
! @. }6 h& f( a; a/ u0 z
最大值,这个工作对应于3 )。for 循环将每一对重量值中较小值和较大值分别与当前的最小值w [ M i n ]和最大值w [ M a x ]进行比较,根据比较结果来修改M i n和M a x(如果必要)。 $ |8 A9 k' B2 ?! f* D/ q4 p* R' x2 x1 h7 g9 q. F- m
下面进行复杂性分析。注意到当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次。% V, ]1 h) p* }% q5 @8 H
* Z! U. {' k6 K$ q( S% X
程序14-1 找出最小值和最大值的非递归程序1 X! y6 k$ h+ l
) Y, m4 e1 L. T; ]
template<CLASS T> 7 M. Y5 k0 v" Y* v0 B/ M" w: Y$ O" Q: b' B9 t5 h8 G
bool MinMax(T w[], int n, T& Min, T& Max)" s; R% A" l, U$ |0 R7 t3 Q
* ?- Q, c9 n& Q0 I
{// 寻找w [ 0 : n - 1 ]中的最小和最大值 4 S) Z! m9 n7 j 5 x X: V" T) i! h8 K7 v( e4 |1 g// 如果少于一个元素,则返回f a l s e & L' R6 q3 G( a* o1 ]" u3 b6 a D: c; u5 m% t) |. V- [
// 特殊情形: n <= 1' j+ C4 X: t/ ~/ r+ w, v& n9 A: Z
- R, P% a7 w* v
if (n < 1) return false;- Z4 s2 Z$ G- o4 x, K3 V; l, Z1 d
' y2 ?8 E% v& F7 Q( V5 cif (n == 1) {Min = Max = 0; - t4 f4 k4 l9 t. o% @- Q5 O 2 R6 j/ I5 M, W' k# yreturn true;} # C3 c/ j/ E& K8 z, Y# \% s, w: i, P, [, b " C2 v3 v3 L" P+ ~ t" f/ /对Min 和M a x进行初始化8 i. V* V, s: x! t& M1 y4 H3 Q
% @! |$ d# h# A, qint s; // 循环起点0 A w9 s7 C5 q1 H
; Y, R8 b6 N# G6 n5 Y) M$ ~* mif (n % 2) {// n 为奇数+ ]; g* e8 h% O9 b
6 |% h# F0 J0 {) `
Min = Max = 0; 4 D% ]" @# d& Y. K, i ( ]0 i H) Q3 }3 [8 {s = 1;} ( Q4 d' S& V/ f! v6 o1 m2 X , B) E7 m% {; ^9 welse {// n为偶数,比较第一对9 Y5 Q: Q1 J1 _; h* |
1 _# ], T/ {& @: Z M. ~
if (w[0] > w[1]) { " W& w' A. j8 A/ A- ]* b+ q) W( K, E9 m
Min = 1; 3 W! m% R! ~* \9 C2 } # ~- C9 a: F. s- V4 W; w) pMax = 0;} " K4 d% Y9 Z# Y8 ?* y: O2 J5 Z4 X9 G2 n9 V. S; R
else {Min = 0; " @8 `# s& r9 S5 W) k A $ @* a o y qMax = 1;} " r+ A3 [, \$ |8 h h' c( Q @5 R5 j1 F4 n; ~ zs = 2;}7 s3 J u; }& _- h) R* k3 }1 |$ u
( U5 N' I H+ W; Z// 比较余下的数对4 C# A$ r' l2 k) K; C5 @
- Z+ g2 ^. M& y2 J1 M3 J8 l
for (int i = s; i < n; i += 2) {9 H5 n1 u d& }: S1 O
/ @2 C* Y0 D# {! X: B& w, S- P8 k// 寻找w 和w [ i + 1 ]中的较大者 7 a C0 |, T! U1 a* S- U) Q3 U/ S. c, j& H
// 然后将较大者与w [ M a x ]进行比较 . |6 y. E* ^6 E+ i! Q; D6 P$ l( t# C4 i8 v+ N: B* `
// 将较小者与w [ M i n ]进行比较 ; F6 B P4 X9 S% `8 g% L# F! u/ G) J1 a9 ^
if (w > w[i+1]) { & h8 q2 L6 h. ]$ G O9 E! Q, k& e8 r5 f8 o
if (w > w[Max]) Max = i; ^8 `! W- M/ b3 h" c. O6 o8 a# l 6 Y. N( L3 ^$ \. eif (w[i+1] < w[Min]) Min = i + 1;}( i" H) o# z* X& W3 @5 U& ]
$ H2 ]0 ^% M$ Q) Z. `& g; Celse {9 e: Q# b. \( y0 V
5 ]0 O- z7 u$ e) {) S A, T$ K
if (w[i+1] > w[Max]) Max = i + 1; + n- g0 S8 H* S8 x& m! J& a+ ~, S/ h, t7 d- ~% A* ?/ e c7 ~
if (w < w[Min]) Min = i;}8 w7 D$ l4 ^* |' Y
; j8 w1 M* @" V} 4 F4 q, N0 `9 j O2 U" K5 p! g# P9 n: H5 e3 V) _$ y
return true; / u6 @$ v( K2 a9 o: V+ g7 w5 V" G3 Q, n: i( y3 c
} 6 U l& }7 A8 I, v8 X/ E F% D J+ _9 H
练习$ L7 M5 c8 }$ l1 R- K
9 ?' r7 D- c A/ }* t" `' S: a! D1. 将例1 4 - 1的分而治之算法扩充到n> 1个硬币的情形。需要进行多少次重量的比较?# v- N F* t ]& {
8 A, _2 Y5 {* n# ~3 i
2. 考虑例1 4 - 1的伪币问题。假设把条件“伪币比真币轻”改为“伪币与真币的重量不同”,同样假定袋中有n 个硬币。! e* A: `0 i" g3 ]; h4 D