/ L3 I5 l: v$ [" e( L- n& I4 g: R根据上述步骤,可以得出程序1 4 - 1的非递归代码。该程序用于寻找到数组w [ 0 : n - 1 ]中的最小数和最大数,若n < 1,则程序返回f a l s e,否则返回t r u e。 / d; ~, V; ^* _5 }- H * v. Q6 N1 Z; R5 P当n≥1时,程序1 4 - 1给M i n和M a x置初值以使w [ M i n ]是最小的重量,w [ M a x ]为最大的重量。" z3 D8 d3 t& q: s8 Q0 S* j5 a
; y0 r8 Q0 ` y( q7 w
首先处理n≤1的情况。若n>1且为奇数,第一个重量w [ 0 ]将成为最小值和最大值的候选值,因此将有偶数个重量值w [ 1 : n - 1 ]参与f o r循环。当n 是偶数时,首先将两个重量值放在for 循环外进行比较,较小和较大的重量值分别置为Min和Max,因此也有偶数个重量值w[2:n-1]参与for循环。 / Q: }" H( p7 w7 B$ c' C8 x, H" Z: X/ c8 M$ y
在for 循环中,外层if 通过比较确定( w [ i ] , w [ i + 1 ] )中的较大和较小者。此工作与前面提到的分而治之算法步骤中的2) 相对应,而内层的i f负责找出较小重量值和较大重量值中的最小值和 * w: ~. Z$ j% V' l9 d 6 }4 u3 _* G( g3 V最大值,这个工作对应于3 )。for 循环将每一对重量值中较小值和较大值分别与当前的最小值w [ M i n ]和最大值w [ M a x ]进行比较,根据比较结果来修改M i n和M a x(如果必要)。& t5 b6 }0 { U$ Y5 C
+ j# L6 N7 ~- m" F4 R下面进行复杂性分析。注意到当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次。 - m! Q% O7 }) N X7 c! @7 w o% m/ X7 }: B5 I程序14-1 找出最小值和最大值的非递归程序4 g# G# S) `/ \, d& z w$ G p
, k# C' M9 ?- ?0 P
template<CLASS T>, w1 B7 ^6 i% M/ Y: E" q4 `
1 q! W: q4 c: }9 B% Mbool MinMax(T w[], int n, T& Min, T& Max); r9 J" D3 y2 N! s( j
* i% l- S$ L N2 c: o# B
{// 寻找w [ 0 : n - 1 ]中的最小和最大值0 G( B; p. W( J* Y$ D
7 m% _: }7 ?/ i/ f. x& u/ V// 如果少于一个元素,则返回f a l s e 2 K6 n8 @ e% f; O & N$ n5 q0 m* I( `9 V2 g// 特殊情形: n <= 1 + Z( O) G) g; F( Y9 o, g1 V8 b( G' b ; ^3 h/ o, @1 Hif (n < 1) return false; 0 r) z& Z2 J. `5 H2 p4 T) l" g3 a7 x' y2 a9 H1 B
if (n == 1) {Min = Max = 0;' f. K2 P5 C0 L
0 L' ~( P; }* Y9 x1 K8 ^
return true;} , e) c4 ?9 L/ t7 v) H3 |9 _ n1 J* i 5 ^% @" r; u+ b$ ]" d/ /对Min 和M a x进行初始化 j6 y! Q; M8 ^, d8 ]$ e* u! g7 _5 W
int s; // 循环起点+ I# I4 p$ ]/ `* g7 k
8 h# R* y8 ]4 x" p* w
if (n % 2) {// n 为奇数, F$ A: v3 `4 q( L% H# m& c3 ^
; I$ i$ ?5 T. a. @) PMin = Max = 0;5 \- w; [$ s0 g* U+ H+ Z& B
" @: J2 ~0 N7 b$ o- E9 a. U! _7 I
s = 1;} 9 i$ W8 G+ D6 m8 e7 J2 W7 i i: x1 D. Z7 H e; c
else {// n为偶数,比较第一对# y! X8 M: K8 O- Y9 [ p+ N3 s
4 ?6 n; k( @, @, u/ L
if (w[0] > w[1]) { 8 o: ], n: a6 A * x4 F J# f% [Min = 1; 4 i3 x, C: t" `* |7 @ h. q ' ]# b% l% u: [/ I# ^5 eMax = 0;}8 p" K% t* t( X! A3 @+ I2 X6 W
. j. t# X/ h6 [9 }5 qs = 2;} 9 S9 S$ b* t! H6 C3 R. P4 \ 1 D7 f9 F) d' D. ?// 比较余下的数对 4 A% a- o$ H* o+ t / q) I# L8 n }for (int i = s; i < n; i += 2) { 1 o% ~7 R( f _' ]; L% q3 s3 r- `- A/ E8 Z! c4 Q( u
// 寻找w 和w [ i + 1 ]中的较大者 + i4 `' M8 t8 S) \ ! a1 z+ \* @/ Y3 J) l: r6 G// 然后将较大者与w [ M a x ]进行比较 2 F2 S5 ^5 `5 h: H" n8 a% T3 R; N) X
// 将较小者与w [ M i n ]进行比较0 C7 E8 r% n) l6 v1 z, ~
" c! b6 P- _5 uif (w > w[i+1]) { . S% ?% V+ P/ Q( F1 `1 z" p5 L7 G" t/ x1 n
if (w > w[Max]) Max = i;) T l' a2 T( i! d+ E
2 W. j0 [' u. V) }
if (w[i+1] < w[Min]) Min = i + 1;} # ^* B. Y; U. u6 C: L. ?: _! o# w( K' V/ i( F9 s
else { 0 j$ H. l9 F- C3 S6 ]; K9 E3 a : X1 L Q/ E! Rif (w[i+1] > w[Max]) Max = i + 1; 2 b, t. A, [! y: `6 W1 g9 G$ S6 H9 u+ a1 F' a
if (w < w[Min]) Min = i;}% Y, u1 y* L; }* D
0 ~, g" ~% p; P, w4 O. B
} , d. Z* x! |( B, M, H" M, ~$ J * F, j# `% i. w/ I* H4 ?) Nreturn true; # q0 M) j4 ]2 u- o D, X+ G! s9 M1 z# c
} & ^- H* A+ G; _8 t % k9 I) t2 e' s+ W1 }7 C& i练习7 {8 ?) ^ k E' O
1 ?7 X5 g. X. E# W' f1. 将例1 4 - 1的分而治之算法扩充到n> 1个硬币的情形。需要进行多少次重量的比较? & W1 _: b0 r4 F, v: C 9 G* S2 b# A! ~2. 考虑例1 4 - 1的伪币问题。假设把条件“伪币比真币轻”改为“伪币与真币的重量不同”,同样假定袋中有n 个硬币。 & G7 [1 x1 P7 J+ I- ^3 @+ |0 T9 ?2 O1 P6 C4 F0 z( u' X
1) 给出相应分而治之算法的形式化描述,该算法可输出信息“不存在伪币”或找出伪币。算法应递归地将大的问题划分成两个较小的问题。需要多少次比较才能找到伪币(如果存在伪币)? 9 m4 h( o" R: ?4 U4 ]4 i! L" ]4 R$ s+ ]$ w3 u1 w# U& S6 f/ j
2) 重复1) ,但把大问题划分为三个较小问题。 5 e& L" Q8 Q3 { + Z/ r" `, t+ l' N" b3. 1) 编写一个C++ 程序,实现例1 4 - 2中寻找n 个元素中最大值和最小值的两种方案。使用递归来完成分而治之方案。 ( S2 v& \! S4 ~ ( K9 y9 B) J" M R0 m) L2) 程序2 - 2 6和2 - 2 7是另外两个寻找n 个元素中最大值和最小值的代码。试分别计算出每段程序所需要的最少和最大比较次数。 4 n' G# p0 Z: ` " o- E* }& O% ]% E/ ]3) 在n 分别等于1 0 0,1 0 0 0或10 000的情况下,比较1)、2)中的程序和程序1 4 - 1的运行时间。对于程序2 - 2 7,使用平均时间和最坏情况下的时间。1)中的程序和程序2 - 2 6应具有相同的平均时间和最坏情况下的时间。! t- w. {8 J! e+ N
. J2 T5 f& i! G0 Z m) M
4) 注意到如果比较操作的开销不是很高,分而治之算法在最坏情况下不会比其他算法优越,为什么?它的平均时间优于程序2 - 2 7吗?为什么?8 Q$ T5 [/ B' n8 ^
9 F$ o( j c* |0 V( I( w* u: V& [6 b
4. 证明直接运用公式(1 4 -2)~(1 4 - 5)得出结果的矩阵乘法的分而治之算法的复杂性为(n3 )。因此相应的分而治之程序将比程序2 - 2 4要慢。 . k: j9 k, }5 ? @+ n/ {' c7 k1 C% D
5. 用迭代的方法来证明公式(1 4 - 6)的递归值为(n l og27)。 , j; G* g% P% Q. L: Q: s$ G- E3 r" z5 f) A+ |* p- x
*6. 编写S t r a s s e n矩阵乘法程序。利用不同的k 值(见公式(1 4 - 6))进行实验,以确定k 为何值时程序性能最佳。比较程序及程序2 - 2 4的运行时间。可取n 为2的幂来进行比较。9 [5 l% E/ o0 C4 m1 B$ y
, [- p: R8 K6 ^; p
7. 当n 不是2的幂时,可以通过增加矩阵的行和列来得到一个大小为2的幂的矩阵。假设使用最少的行数和列数将矩阵扩充为m 阶矩阵,其中m 为2的幂。 6 S( ~' [/ s& A- M8 B5 x$ J& Y5 f1 {1 y$ m' }4 L
1) 求m / n。7 ^ k9 k, m5 S; k8 D* U3 b
- ~' f* o2 F2 Y0 a) K
2) 可使用哪些矩阵项组成新的行和列,以使新矩阵A' 和B' 相乘时,原来的矩阵A和B相乘的结果会出现在C' 的左上角?- x" f( o# P' h- z' j
) X. g* U6 v/ \2 p2 V3 ~# ~
3) 使用S t r a s s e n方法计算A' * B' 所需要的时间为(m2.81 )。给出以n 为变量的运行时间表达式。 </P>