5 u1 n! L# K5 G2 A4 Z( c+ _0 z3 X根据以上结果可得:0 s/ }* j0 j' [9 E2 W; l
. D7 E* C: q. X$ m
对于上面这个2×2的例子,使用分而治之算法需要7次乘法和1 8次加/减法运算。而直接使用公式(2 - 1),则需要8次乘法和7次加/减法。要想使分而治之算法更快一些,则一次乘法所花费的时间必须比11次加/减法的时间要长。 % T; V1 W1 r0 ?* W G% |. I [$ B, X9 `3 T: |) n假定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次加/减法的开销。 8 F5 \8 T, c) m* d6 o0 i% q A; F( V. H$ M: m4 I/ m1 W假定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方法快。. a. h5 ~+ |1 J3 P! ?
0 \1 E, W# Y3 d! @2 |0 k( j w根据上述步骤,可以得出程序1 4 - 1的非递归代码。该程序用于寻找到数组w [ 0 : n - 1 ]中的最小数和最大数,若n < 1,则程序返回f a l s e,否则返回t r u e。 8 R% j1 q, x" [: l6 `) g. y; t u3 P9 T! O3 u/ o/ w a5 P0 Z8 Z
当n≥1时,程序1 4 - 1给M i n和M a x置初值以使w [ M i n ]是最小的重量,w [ M a x ]为最大的重量。% ?) o4 \. P8 j/ u; v; o( d
8 c: O8 l* n+ W R: L
首先处理n≤1的情况。若n>1且为奇数,第一个重量w [ 0 ]将成为最小值和最大值的候选值,因此将有偶数个重量值w [ 1 : n - 1 ]参与f o r循环。当n 是偶数时,首先将两个重量值放在for 循环外进行比较,较小和较大的重量值分别置为Min和Max,因此也有偶数个重量值w[2:n-1]参与for循环。9 j7 @& e% P' V2 K% d
1 B' u# K9 ~8 ?4 L _
在for 循环中,外层if 通过比较确定( w [ i ] , w [ i + 1 ] )中的较大和较小者。此工作与前面提到的分而治之算法步骤中的2) 相对应,而内层的i f负责找出较小重量值和较大重量值中的最小值和 ( K1 @5 R e: d4 D7 E4 I : k, Q5 C2 B5 `2 l* L- N最大值,这个工作对应于3 )。for 循环将每一对重量值中较小值和较大值分别与当前的最小值w [ M i n ]和最大值w [ M a x ]进行比较,根据比较结果来修改M i n和M a x(如果必要)。 - U! n/ C7 l3 G4 Z0 _2 t ) k* \! Z( K+ r! O& D) i* W5 o下面进行复杂性分析。注意到当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次。0 \0 Y. s) s+ X( `7 `, {3 K
3 \0 t& A' s. E; B u# h. k: o/ c- F
程序14-1 找出最小值和最大值的非递归程序0 q3 s ^( M5 M Q! b
: Y% _. V0 D1 Z9 ]. C: Y& y
template<CLASS T> / K$ q7 d: @" E- _ ( ?! {& ^# ?9 Zbool MinMax(T w[], int n, T& Min, T& Max); t; g. P4 `+ d$ H" t
* [5 w# U8 u* l) e{// 寻找w [ 0 : n - 1 ]中的最小和最大值- O8 Z0 J7 u+ v6 M* y3 _9 C A, a6 m
v0 ~' {5 k8 Q' ^// 如果少于一个元素,则返回f a l s e: X4 n( n% ~% P# b: T7 h
4 @9 E! c, A& h2 B% l// 特殊情形: n <= 1; k7 k1 f8 h% C3 g3 o
$ t4 `. N7 f% |# g& D! v// 比较余下的数对; I" h7 q2 [' z7 W
: j! L& u/ I5 q3 g9 o7 R& c/ U
for (int i = s; i < n; i += 2) { ( N% H0 @6 N+ s) _* J9 F 8 R! h: S2 B, \2 A7 D6 B// 寻找w 和w [ i + 1 ]中的较大者 + w6 ]" V; V# z& T' u% G( |6 ] ) l, }6 l( G4 L( c! z// 然后将较大者与w [ M a x ]进行比较9 K- _- U$ m( \. M0 J5 r
5 R- c7 H/ |$ O! `, A; T# a
// 将较小者与w [ M i n ]进行比较9 v& S3 p. H3 N9 i% W1 P: `# R6 n
1 Z( H2 E- k/ w# t6 {if (w > w[i+1]) {# b, X" ^+ r2 c
9 N# I. N1 z( a4 I
if (w > w[Max]) Max = i;' b/ G) Y9 R9 g+ e2 C
* B6 t# K% J* z5 |" \" X! r
if (w[i+1] < w[Min]) Min = i + 1;} ! q, E S. y% d3 N& d, k& N2 Q- c$ e8 ]0 f0 H
else {: y) N) v5 D! X$ n! z
, u1 @# E# R* t9 h, Mif (w[i+1] > w[Max]) Max = i + 1;6 R: I4 a, Y+ n; P- u; U
% t1 k/ A4 ]" P. i1 _1 k4 R
if (w < w[Min]) Min = i;}1 r/ b- Z2 o* I: R; q
% L5 y1 c$ _2 _1 i}1 R: Z, y* Y" c, {1 Z
6 J" V) p' F) \, Ireturn true;% l7 V! G6 f3 V5 i" V- R5 O
* m. H: B0 q+ C7 b& K
} # k7 }% |9 [. X6 G# k3 V9 X; [$ e2 h! ]. X8 I4 v
练习8 c: m! K; ~; |: B: B7 C
5 d+ Q! r4 G2 g+ H1 c
1. 将例1 4 - 1的分而治之算法扩充到n> 1个硬币的情形。需要进行多少次重量的比较? # x! m1 j% _) r" ^+ X- E2 Q% }5 m* F: x4 x* S, f
2. 考虑例1 4 - 1的伪币问题。假设把条件“伪币比真币轻”改为“伪币与真币的重量不同”,同样假定袋中有n 个硬币。 # o7 ~& \7 [- j( C- _7 B2 H: f0 }2 M5 o# S8 L
1) 给出相应分而治之算法的形式化描述,该算法可输出信息“不存在伪币”或找出伪币。算法应递归地将大的问题划分成两个较小的问题。需要多少次比较才能找到伪币(如果存在伪币)?4 p4 m; Q! c" K' W2 ~) v5 H
4 g0 P; }2 p( N2 ~, L" H3 Q) p
2) 重复1) ,但把大问题划分为三个较小问题。% @3 S E( s* L* w, C0 u7 k' x P
. [ p- r" e+ k% o( _5 ~
3. 1) 编写一个C++ 程序,实现例1 4 - 2中寻找n 个元素中最大值和最小值的两种方案。使用递归来完成分而治之方案。 & ^- Z) b: |* E- R% h ; l m; T: T8 j+ K- c+ p2) 程序2 - 2 6和2 - 2 7是另外两个寻找n 个元素中最大值和最小值的代码。试分别计算出每段程序所需要的最少和最大比较次数。 $ l0 K+ t% S6 N" d' J8 C: c* q# A% U! L
3) 在n 分别等于1 0 0,1 0 0 0或10 000的情况下,比较1)、2)中的程序和程序1 4 - 1的运行时间。对于程序2 - 2 7,使用平均时间和最坏情况下的时间。1)中的程序和程序2 - 2 6应具有相同的平均时间和最坏情况下的时间。1 }8 A; C5 J! g) Z