" [7 k# V. P( j' A9 n* l2 Mfloat x, y; // 点坐标6 G. w% ~; t3 n( B0 _3 F
7 R: T( x! {3 a$ \# K
} ; . @) a7 E" F- Z, k7 D $ S7 Q7 Z( a" p' J+ k5 W所输入的n 个点可以用数组X来表示。假设X中的点已按照x 坐标排序,在分割过程中如果当前考察的点是X [l :r],那么首先计算m= (l+r) / 2,X[ l:m]中的点属于A,剩下的点属于B。计算出A和B中的最近点对之后,还需要计算RA 和RB,然后确定是否存在更近的点对,其中一点属于RA,另一点属于RB。如果点已按y 坐标排序,那么可以用一种很简单的方式来测试图1 4 - 1 6。按y 坐标排序的点保存在另一个使用类P o i n t 2 (见程序14-8) 的数组中。注意到在P o i n t 2类中,为了便于y 坐标排序,已重载了操作符<=。成员p 用于指向X中的对应点。3 L" q6 o0 V2 r0 d
, G+ `+ r1 B8 Y, D确定了必要的数据结构之后,再来看看所要产生的代码。首先定义一个模板函数d i s t (见程序1 4 - 9 )来计算点a, b 之间的距离。T可能是P o i n t 1或P o i n t 2,因此d i s t必须是P o i n t 1和P o i n t 2类的友元。3 n, S8 M2 \* r h/ y
& h$ i, l# K0 ~8 P7 ^9 {程序14-9 计算两点距离 ! K d7 Q* |1 c) H7 }! }5 u# p0 J; d+ b2 B
template<CLASS T> * W8 w, {# Q! R* D7 a7 b9 t7 p4 g: J! R- V H
inline float dist(const T& u, const T& v) - U8 Z+ t; Z5 u( x/ @0 G; t) g& @. a) J
{ / /计算点u 和v之间的距离 ! B, _- R9 b9 U. L+ W I" O ' n) F# f- F2 s5 L: Z0 T5 ~float dx = u.x-v. x ; 1 B1 Z7 s3 c6 w, W0 [* ^ 5 a' P1 J' K& O, a% c2 lfloat dy = u.y-v. y ;( |. |4 C' T4 N
2 B7 m9 K$ q7 \% R9 A# }* a) U& r
return sqrt(dx * dx + dy * dy); * ~/ P5 n X( p/ F/ a E( v' D . J' P3 L o- |. D9 M}5 S, J J; K2 a7 G6 p( m: M5 y
7 [. a$ z& m" p/ S7 _" S如果点的数目少于两个,则函数c l o s e s t (见程序1 4 - 1 0 )返回f a l s e,如果成功时函数返回t r u e。当函数成功时,在参数a 和b 中返回距离最近的两个点,在参数d 中返回距离。代码首先验证至少存在两点,然后使用M e rg e S o r t函数(见程序14-3) 按x 坐标对X中的点排序。接下来把这些点复制到数组Y中并按y 坐标进行排序。排序完成时,对任一个i,有Y [i ] . y≤Y [i+ 1 ] . y,并且Y [i ] .p给出了点i 在X中的位置。上述准备工作做完以后,调用函数close (见程序1 4 - 11 ),该函数实际求解最近点对。% d3 V- |7 N% \ x
6 U9 k& `$ I' g3 m5 t( B% z0 j程序14-10 预处理及调用c l o s e- \) K# x# ] }6 S2 b3 ?* E7 ^
8 d% E+ w8 x L. {* ?1 @bool closest(Point1 X[], int n, Point1& a, Point1& b, float& d) + l" e+ [& l% R4 m# B3 F; R# a! O/ @7 w7 B
{// 在n >= 2 个点中寻找最近点对! w/ ~+ E. g" A, C( ?" ~
9 W/ L* ^0 B/ R& Y; M// 如果少于2个点,则返回f a l s e * u1 E+ s" K2 }, G! a) D. ~$ y9 W5 y% Q% d/ b; F
// 否则,在a 和b中返回距离最近的两个点 ( z* M( j! _7 J/ f/ o* m! c1 i- Y3 |, W' b9 E
if (n < 2) return false;7 {' ]) e6 _6 u C4 H, h, \
, m( p. V! A! h: R
// 按x坐标排序0 t& r" [5 g* z! T& u0 G2 O
: z2 w6 q; U1 s4 P# }$ z- J% p# E
M e r g e S o r t ( X , n ) ;# t* U/ T+ g, [7 V: N6 q
, t0 U$ P0 @1 I7 P& E5 @1 ~// 创建一个按y坐标排序的点数组) b, u Q' v* P" M7 _4 m8 ^0 D6 D. Y
7 K4 Q) l0 I' ^7 }
Point2 *Y = new Point2 [n];& Z6 U1 }2 b' h) r8 H
1 v1 L7 T/ W) w. L O& KM e r g e S o r t ( Y,n); // 按y坐标排序7 H! W; f- G* o; J& O
, S7 Z) c- O1 L
// 创建临时数组4 A0 S& E4 c, k% N% ` T4 I
2 H3 n. I8 O+ g+ jPoint2 *Z = new Point2 [n];) q" o& H: |4 F8 M7 A! ?
" p& O5 H4 s, a& j// 寻找最近点对/ g, g0 _, ~. F
+ k5 A( C6 v9 f+ P& W- [c l o s e ( X , Y, Z , 0 , n - 1 , a , b , d ) ;$ c- K0 |9 p3 ]
6 U- u- Q+ g3 F$ p9 j. q
// 删除数组并返回 $ E5 ]) _6 E6 D* J2 P2 l2 u9 \- [) M: N; T5 |
delete [] Y; 7 u4 }1 e% H4 m* X0 o , L+ J+ B( h. d! \$ m( sdelete [] Z;9 X- B1 e2 U6 I d. s
' d0 I( y c7 b2 [5 N" zreturn true; : C. j6 D- _2 D5 @- W ! s0 |" D6 F5 r8 y}) K: F$ T% V& [& V0 M* U
' f" w3 J4 s3 S" B3 {
程序1 4 - 11 计算最近点对 7 x. T9 _' u4 t( l0 w5 C7 O& [# e0 r- l. |
void close(Point1 X[], Point2 Y[], Point2 Z[], int l, int r, Point1& a, Point1& b, float& d) % l( b/ Q5 B1 q% A9 v0 `0 p. _$ s/ p. p& l1 z
{//X[l:r] 按x坐标排序 % a4 d: J9 w* w( e! ?2 v/ j$ o; r t2 H; S0 d1 ~
//Y[l:r] 按y坐标排序( s1 |* @3 `1 D
m4 y+ X3 z5 f! U0 M: Q8 U1 f) y7 }* aif (r-l == 1) {// 两个点7 o, k# A) f% F: {/ U
$ I9 O1 ], ] x
a = X[l]; " K8 o$ h6 o; i$ J6 [: H, H 1 M& Z& Z! Q7 f% [: ?+ hb = X[r];8 q7 S6 B5 d8 @1 r
: `: Z3 I- j9 z) V' pd = dist(X[l], X[r]);! B' J. s% ?3 d# D
& x5 W* k% t# s: {/ ~
r e t u r n ; }2 U2 t- \1 x' L# o8 X; p
! [7 Q1 {1 A* z* W6 \( L
if (r-l == 2) {// 三个点: g; m/ [# p% g+ ?6 o. `4 x! z
9 n, b# h# j) B3 c) R// 计算所有点对之间的距离8 x' s" G3 o1 o" L# x3 ~
, \- D6 Y6 A3 r7 n! d& gb = X[r]; ' i# i$ K% ~8 C5 ]3 K3 [1 X* E6 j6 a% r' D
d = d2;}. i+ ]% [; z; v5 ~1 q% \; P2 a; x
$ Z% Y1 c6 }" K/ ]! e5 ~5 `; F/ [8 t
else {a = X[l];* r7 M# O6 |( K0 n
" R$ g+ B# w+ n0 c3 ~
b = X[r]; * {/ z: n" u; x# t+ s ~7 G& r- [" b& m ^# t
d = d3;}- \' P X* E7 @: p/ p/ F/ ~* f
$ I+ [3 G' |* _4 }* x( F5 f' G% j7 u
r e t u r n ; } ! U* t) [* c: g+ N, r 1 ?! i, Q |0 a$ v/ /多于三个点,划分为两部分 " W- ]1 P2 }2 v4 y+ O % b7 S8 |8 a$ V2 qint m = (l+r)/2; // X[l:m] 在A中,余下的在B中! w' i; ~' W' o% v W9 s7 f
4 k; x8 M @& o* C! s* h
// 在Z[l:m] 和Z [ m + 1 : r ]中创建按y排序的表 d% I& X4 N# E7 z6 Y
+ b5 Z ]& a4 C; L3 J$ I! J
int f = l, // Z[l:m]的游标 3 W( `+ [/ A' Z' r5 o( ?; l3 y" k1 k, U
g = m+1; // Z[m+1:r]的游标 $ n7 E' x. t$ t3 W) ?3 t / C: I6 E) n5 P. p. gfor (int i = l; i <= r; i++)- X, n- R6 Z4 A/ z1 m" x9 d3 P
+ X6 n" j" \: {# mif (Y.p > m) Z[g++] = Y;% X9 B! ~4 Q7 K
9 N9 w" C/ a8 f' b* eelse Z[f++] = Y;; j7 g. w9 h7 |8 b
8 ]" s$ f- f& g
// 对以上两个部分进行求解 - \- T0 E: T9 z+ h* ~ 9 ^! Y0 p) ^9 @1 Oc l o s e ( X , Z , Y, l , m , a , b , d ) ; 9 b1 v0 Y! F( I5 _% R& Y7 m4 Z$ H& v9 z2 C/ n# b$ u* [& t& W" Z; N
float dr;1 [4 L l9 r1 Y5 G
6 a9 e8 S" m% N+ j) u" V
Point1 ar, br; 5 j/ _ \ ~- h) l0 E' g, M F: w/ N5 T, g+ {. e' o
c l o s e ( X , Z , Y, m + 1 , r, a r, b r, d r ) ; 6 j7 o M1 b& @- ~( j; P7 W" A* v5 c8 ]9 `) S8 S% Q/ U1 @
// (a,b) 是两者中较近的点对: O/ y, L2 c; `2 [) m) s
) h( _: p* \4 z- D$ z% A% k
if (dr < d) {a = ar;, l3 l) h/ q# d) R) j- O% n
! f% o# s- T! J' L/ F0 ?! F这个递归式与归并排序的递归式完全一样,其结果为t (n) = (nl o gn)。另外,函数c l o s e s t还需耗时(nl o gn)来完成如下额外工作:对X进行排序,创建Y和Z,对Y进行排序。因此分而治之最近点对求解算法的时间复杂性为(nl o gn)。</P>