<>可以运用分而治之方法来解决排序问题,该问题是将n 个元素排成非递减顺序。分而治之方法通常用以下的步骤来进行排序算法:若n 为1,算法终止;否则,将这一元素集合分割成两个或更多个子集合,对每一个子集合分别排序,然后将排好序的子集合归并为一个集合。 4 S6 m v8 I# A6 m' _* B7 R1 c. P, y% B
假设仅将n 个元素的集合分成两个子集合。现在需要确定如何进行子集合的划分。一种可能性就是把前面n- 1个元素放到第一个子集中(称为A),最后一个元素放到第二个子集里(称为B)。按照这种方式对A递归地进行排序。由于B仅含一个元素,所以它已经排序完毕,在A排完序后,只需要用程序2 - 1 0中的函数i n s e r t将A和B合并起来。把这种排序算法与I n s e r t i o n S o r t(见程序2 - 1 5)进行比较,可以发现这种排序算法实际上就是插入排序的递归算法。该算法的复杂性为O (n 2 )。把n 个元素划分成两个子集合的另一种方法是将含有最大值的元素放入B,剩下的放入A中。然后A被递归排序。为了合并排序后的A和B,只需要将B添加到A中即可。假如用函数M a x(见程序1 - 3 1)来找出最大元素,这种排序算法实际上就是S e l e c t i o n S o r t(见程序2 - 7)的递归算法。. K5 y. r) ?5 O) ]* H9 r
u& d U c" p7 ?/ }4 i假如用冒泡过程(见程序2 - 8)来寻找最大元素并把它移到最右边的位置,这种排序算法就是B u b b l e S o r t(见程序2 - 9)的递归算法。这两种递归排序算法的复杂性均为(n2 )。若一旦发现A已经被排好序就终止对A进行递归分割,则算法的复杂性为O(n2 )(见例2 - 1 6和2 - 1 7)。 . |% |: O3 `0 I' h: N# W( G2 N7 B' {8 A1 o- Q X5 f
上述分割方案将n 个元素分成两个极不平衡的集合A和B。A有n- 1个元素,而B仅含一个元素。下面来看一看采用平衡分割法会发生什么情况: A集合中含有n/k 个元素,B中包含其余的元素。递归地使用分而治之方法对A和B进行排序。然后采用一个被称之为归并( m e rg e)的过程,将已排好序的A和B合并成一个集合。 . G/ ~8 E: T+ S+ E4 V7 a5 o, m" i4 Y( w
例2-5 考虑8个元素,值分别为[ 1 0,4,6,3,8,2,5,7 ]。如果选定k = 2,则[ 1 0 , 4 , 6 , 3 ]和[ 8 , 2 , 5 , 7 ]将被分别独立地排序。结果分别为[ 3 , 4 , 6 , 1 0 ]和[ 2 , 5 , 7 , 8 ]。从两个序列的头部开始归并这两个已排序的序列。元素2比3更小,被移到结果序列;3与5进行比较,3被移入结果序列;4与5比较,4被放入结果序列;5和6比较,.。如果选择k= 4,则序列[ 1 0 , 4 ]和[ 6 , 3 , 8 , 2 , 5 , 7 ]将被排序。排序结果分别为[ 4 , 1 0 ]和[ 2 , 3 , 5 , 6 , 7 , 8 ]。当这两个排好序的序列被归并后,即可得所需要的排序序列。% z3 W. G: C* R1 C1 M8 ~" r' x& q& ?
$ ^. L) M6 v( `2 z9 d" V: f0 |图2 - 6给出了分而治之排序算法的伪代码。算法中子集合的数目为2,A中含有n/k个元素。 a" F9 _5 n5 h& }6 n9 v2 S
* ?% [3 b I+ m, P
template<CLASS T> q+ Y' N. @% v! L/ t |# R ; i: A e, r& O' a2 m/ Nvoid sort( T E, int n) 4 D& u, Q) m% c* _$ R2 q+ Z7 z% Z/ ~4 t% x9 g; X( O
{ / /对E中的n 个元素进行排序, k为全局变量+ X% ~) V6 }. b4 o% g
+ ~4 M4 Q6 O, J# ^+ G. s; Nif (n >= k) {! p/ E0 x+ F# v( X8 E- L1 i! R
' v2 [. l8 N% N1 l/ [2 V+ U. q2 F
i = n/k; 1 @; z* c. {4 m2 a6 E: i* Q ! u. T7 L' J5 L, v+ V- O6 Sj = n-i;+ M4 X5 ~9 k& H9 ?
/ Z( D. U( _' e. }7 J; a令A 包含E中的前i 个元素9 a4 n% v1 ]& d2 [# Z& [( c
9 D5 o$ X( o2 C) ]) f
令B 包含E中余下的j 个元素( g4 |+ w6 F# r* n1 f
% n0 |* I/ V7 c9 k) {( Q3 Ms o r t ( A , i ) ;' y0 G- M' l1 |* U8 U3 C
( p! p* A) x- X$ h" x
s o r t ( B , j ) ;2 B/ Z# v1 m) e
; L9 ^4 ^' ^ T- ym e rge(A,B,E,i,j,); //把A 和B 合并到E$ e/ K( E6 w; C' z
: i1 x$ D V) h}! D6 d* D# P& I
* v% @' x6 j8 J5 f2 d" pelse 使用插入排序算法对E 进行排序; R# [, L6 k. ?4 B% C+ l, u' g6 r
& T- T' ]9 C, o2 ?" H
}9 U0 y x+ Q4 H) ]# A( i, z" D' i
: f: |6 Z0 A y; Z3 |& P" B/ \ : O" q3 W" s) ~+ V ' @# }4 f7 ` Qtemplate<CLASS T>; V# V) f/ I7 e9 j8 r
9 D9 G" A( N2 `
M e rgeSort( T a[], int left, int right)) f L$ f) i- I8 G
; m9 @8 ~8 G) j( h{ / /对a [ l e f t : r i g h t ]中的元素进行排序% Y2 L9 L1 U- a6 T! G
; Z# Z1 K3 c& S, b* U; K! B7 Kif (left < right) {//至少两个元素+ ]+ \( o0 O; K4 a/ u5 a
: S* ~# W4 Z* }$ F' x7 d
int i = (left + right)/2; //中心位置 L# d) G3 ]" n9 I
. t$ Z) W. o# E3 ]! q$ P! T* e
M e rgeSort(a, left, i);+ }; W4 ~5 L0 v0 I0 M
* f. e) P+ Z$ r* U7 y! U6 f
M e rgeSort(a, i+1, right); ) l3 j. n7 L& g' |3 g$ j4 u" K$ ^ D! `. G
M e rge(a, b, left, i, right); //从a 合并到b5 B3 c. M9 ?3 Z
- d0 t! O4 W; u {% U1 c) A0 ^Copy(b, a, left, right); //结果放回a # ~$ q& I' N9 w. c' ` + E; W. H# H" V- L1 y} / f- S+ x2 g a0 b - D; r% |5 R4 k H/ _" V: Y}6 F ?) H0 Z) W$ K) n; ]5 H