5 q/ D& y. O4 h: ^$ L0 h5 x2 p8 btemplate<CLASS T> , Z# I7 k4 |$ t! d. M$ N* U1 \5 c , z' l' S9 A& [; |" tM e rgeSort( T a[], int left, int right) ; i: m i: u* @3 W. {2 }1 {2 s9 ]8 A' j
{ / /对a [ l e f t : r i g h t ]中的元素进行排序 U& k# e9 O4 `5 K+ G * U( J! I- Z, {# i1 r/ ^ Rif (left < right) {//至少两个元素/ ~' X8 y+ k& u+ Y- P
0 Y' i6 r7 R4 Y% S2 Eint i = (left + right)/2; //中心位置 / F+ y& O* b5 d, { k/ E% ~! i - t+ ] h7 [: h, {+ n: cM e rgeSort(a, left, i);2 Q5 \- }" k) D8 h2 { u l3 o0 n
- {2 |- I3 ~% [8 h, B$ vM e rgeSort(a, i+1, right);; Y& H8 Q/ @) d
$ O; I* a9 |- i1 F4 P1 h' o% s6 X
M e rge(a, b, left, i, right); //从a 合并到b $ e) ^$ f2 w, U ` 6 C$ H+ u& P8 |; D% J! ]Copy(b, a, left, right); //结果放回a 7 u/ N$ b: N+ b3 I0 _8 u* d. e " l. m: P8 y9 @. S} 8 r5 s# l* G x6 y: Q + x0 Q) n8 _9 }' s# t}% Q& Q- @2 Y8 K% S
- F6 b$ \ ~! R) B7 c图14-7 分而治之排序算法的改进 # s7 p) Y t3 Z" u3 B' o. o. A/ N 0 H7 @. F2 d- X6 o; V3 }4 M' O2 o' G/ \& R2 R0 Q; C
; d9 g% u1 T! K1 |+ ?! S; O: R, |{// 使用归并排序算法对a[0:n-1] 进行排序$ ?1 B, |. a/ C. Q+ v) d/ r
7 y& Y. Q0 t5 E# t9 k
T *b = new T [n]; 9 n: d7 Y8 E/ j; Z2 e9 x! z' _ & V5 V9 i. W" Uint s = 1; // 段的大小# J$ |8 p; k7 a4 m" \/ X Y" P
6 [! `* w8 M# b) k. q V+ y) Owhile (s < n) {8 a5 M7 Y2 Q+ N {3 D7 l" J
; A+ M$ h; A- [3 Y0 HMergePass(a, b, s, n); // 从a归并到b ; ]' ~* Z) I6 H8 [! z9 S# r2 f/ R0 z
s += s;" W: l9 W. R4 F6 u3 ^
$ l; B+ O" c# c' z: N
MergePass(b, a, s, n); // 从b 归并到a : t2 Q% X! Z+ h" V6 f1 e/ ]4 m7 m9 [2 k
s += s; ' f& r1 F5 n* T6 }( m( l( J4 [ `! b
}4 N1 C# O* Z5 C6 i4 L" h
8 ?8 k8 V- Z3 Z/ e( X. N3 Y1 w
}( n6 E# B! S7 }: N: x7 |& y
9 f6 b& ?; \7 k4 N$ c, Q5 [为了完成排序代码,首先需要完成函数M e rg e P a s s。函数M e rg e P a s s(见程序1 4 - 4)仅用来确定欲归并子序列的左端和右端,实际的归并工作由函数M e rg e (见程序1 4 - 5 )来完成。函数M e rg e要求针对类型T定义一个操作符< =。如果需要排序的数据类型是用户自定义类型,则必须重载操作符< =。这种设计方法允许我们按元素的任一个域进行排序。重载操作符< =的目的是用来比较需要排序的域。/ N5 J! U* f* @/ ?8 o
' k6 x( ^: a& A" ~0 S程序14-4 MergePass函数 ; o$ C/ B& i# R9 o1 ]: S4 A$ @' |3 w; x
template<CLASS T> . {5 d$ t U5 L" K8 E# ]% c1 N' ~0 L/ ?# n$ i- B, o+ w8 |3 R8 ^5 Y
void MergePass(T x[], T y[], int s, int n)# W5 Y: _: u) X# d7 P8 p' k: F
' K; j& B4 s' n- |2 Z+ L& K{// 归并大小为s的相邻段$ R! y5 U' y5 u4 U
3 ~# F( U9 r, H T8 K- @. j
int i = 0; r- ~ X' J" R, t, v9 q/ [" \ \% a& J0 b* T0 I- p' W
while (i <= n - 2 * s) {1 g% ]* L* G r$ ]$ v. k8 R
7 y3 h( F- \2 _/ T// 归并两个大小为s的相邻段 % k9 T2 l3 O% k$ m# X; J. k 8 _. Q3 @( @5 |! G4 z6 a) fMerge(x, y, i, i+s-1, i+2*s-1);" q o7 i4 i4 t' `( G& b g1 k
' m: s C# q% g2 u5 t7 p7 H
i = i + 2 * s; . z6 g4 x5 s: H/ m9 ^ 9 ~* L$ b, c2 j9 }7 g! b}' f j* ]: k( z3 B( i5 [$ R& E
( n3 j9 d8 \. i) O+ g ^// 剩下不足2个元素 + j7 y; b7 E* |2 p2 x8 n' X. ^2 l+ \) n; [( u- D4 d
if (i + s < n) Merge(x, y, i, i+s-1, n-1); " a3 e6 R4 Z% d' l# q# c. W / k6 L; E7 A% [3 K1 I- oelse for (int j = i; j <= n-1; j++) 4 y) X1 e* z% \! g6 {: n ) `; h* M, y" L; E/ R) b// 把最后一段复制到y 9 D/ K& I0 P2 k, D. b3 i+ y6 N9 ^4 l0 M6 l2 a
y[j] = x[j]; $ r# I5 u6 h: _) t; i( \* v+ T8 m2 _ 8 h, g D) V! A8 ~" c }}8 e3 }, Z7 S4 A$ ~. U7 {% Q' u \3 P5 m
' V! M1 M. }0 I- _" W: [- `+ B程序14-5 Merge函数- q4 O: S# W8 O# X4 I4 j5 L$ t
! }( `6 d$ o0 o
template<CLASS T>" Y" S! K4 P) u$ T: i' i1 x' V" E$ d
! U9 k \7 a, S$ J. @% R
void Merge(T c[], T d[], int l, int m, int r) + V( |5 i9 `1 @( R2 j5 T1 @0 g$ |6 u% n( I
{// 把c[l:m]] 和c[m:r] 归并到d [ l : r ] . ! a6 w* O9 l9 Z; j4 l5 a 3 B- l c8 h6 F( `int i = l, // 第一段的游标/ Y5 ]0 r; x5 @3 P
4 l' m3 E, P6 S/ p5 Y$ a
j = m+1, // 第二段的游标 % B; ^, Z" P1 F# B- O, Y7 q; I. F 8 W; g+ C$ F% a/ K) N1 Bk = l; // 结果的游标' U9 c; X6 U( H& U- x
$ F1 Q9 M; y' t, ?' z7 Y! e& ]8 i2 i/ /只要在段中存在i和j,则不断进行归并 , b( q& t1 a8 B7 K. h8 q L# o + s) ]) O3 E! U! k, H2 rwhile ((i <= m) && (j <= r))' b0 q# g$ b6 L- n! Q" w
, a4 D2 e, V; Z% X/ k9 P- jif (c <= c[j]) d[k++] = c[i++];/ L1 [. b( t$ g' [. u! f- s! S0 y
, ^, t) B9 o4 R
else d[k++] = c[j++];" i& L( q! u2 m3 J- g
, J3 U& m0 z4 x) k6 @6 s) w// 考虑余下的部分 + }& c0 \ {: C9 {: |8 l$ k" Z2 w
if (i > m) for (int q = j; q <= r; q++)9 w( V6 ~2 T, T3 u, w' F
. k# S% e( [1 z/ A( ]d[k++] = c[q]; / }/ F- ?% @4 d" i. J" c9 ^( u5 E* k" ?% i& L# ^
else for (int q = i; q <= m; q++)" x& D6 K% Y. a, b* _# F
0 ~4 Q4 [$ i3 H7 K8 C
d[k++] = c[q]; + p9 S( P: d- G ! m d) N. H/ P} ! U$ m# v* j9 I/ q5 [, T3 r * f1 Q5 ] k. G自然归并排序(natural merge sort)是基本归并排序(见程序1 4 - 3)的一种变化。它首先对输入序列中已经存在的有序子序列进行归并。例如,元素序列[ 4,8,3,7,1,5,6,2 ]中包含有序的子序列[ 4,8 ],[ 3,7 ],[ 1,5,6 ]和[ 2 ],这些子序列是按从左至右的顺序对元素表进行扫描而产生的,若位置i 的元素比位置i+ 1的元素大,则从位置i 进行分割。对于上面这个元素序列,可找到四个子序列,子序列1和子序列2归并可得[ 3 , 4 , 7 , 8 ],子序列3和子序列4归并可得[ 1 , 2 , 5 , 6 ],最后,归并这两个子序列得到[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ]。因此,对于上述元素序列,仅仅使用了两趟归并,而程序1 4 - 3从大小为1的子序列开始,需使用三趟归并。作为一个极端的例子,假设输入的元素序列已经排好序并有n个元素,自然归并排序法将准确地识别该序列不必进行归并排序,但程序1 4 - 3仍需要进行[ l o g2 n] 趟归并。因此自然归并排序将在(n) 的时间内完成排序。而程序1 4 - 3将花费(n l o gn) 的时间。</P>