9 S ~& `# c$ ~friend bool closest(Point1 *, int, Point1&, Point1&,float&);3 p8 i3 D. Y2 g" }7 b) c) t
+ b: @. p1 d1 [! T
friend void main();! |( h+ q# K: P$ a4 }8 ~1 g
) s8 G' j0 U* o3 L, W% V/ Pp u b l i c :& A' ?0 I- @' g* u& U
6 ]5 M! \! V4 c: x
int operator<=(Point1 a) const* H i+ v/ r+ n% d6 k2 k
8 [0 l5 M( B; O/ a
{return (x <= a.x);}" s8 o# g/ e. d4 c5 J
4 I2 Q9 L% Q2 Q6 D
p r i v a t e :" t0 v, Q/ }& v! Y
0 Y& T3 g$ Y$ M, @1 H' Sfriend bool closest(Point1 *, int, Point1&, Point1&, float&);3 r {, Z$ f) y( U+ u6 N
4 @% i) G! H8 O5 A6 e' \
friend void main(); 0 z' C" D# r$ l$ @, O7 X5 a/ D7 V) W$ Q3 ^$ ~2 O2 z! a
p u b l i c : 4 s# B7 K1 Q) e, y1 F# Q1 j5 ?
int operator<=(Point2 a) const4 ~& h1 Z# q/ Y+ }+ I, j
2 z2 o- {" y9 h
{return (y <= a.y);} & u8 P$ k4 a- L5 }7 X( A% a; T$ x! z$ x( H, s7 G
p r i v a t e :# G! l7 w, B* [
% q$ i6 i5 u Q, K! O+ q0 \3 B$ Rint p; // 数组X中相同点的索引6 H6 ~' ~( C5 u
; H% A6 Q; T2 f+ X% O
float x, y; // 点坐标& |# k# s; O# G7 }
7 m, I( l# _! c$ X) Y
} ;% V5 b9 D; \) J* T0 s
7 X" H; M/ s1 D5 T# Q所输入的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中的对应点。 9 ?1 g% R9 f+ n; [" C& D, [. K, K7 X! ^4 Y) p# s& L
确定了必要的数据结构之后,再来看看所要产生的代码。首先定义一个模板函数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类的友元。; |( u" v- \: r [
; P% @' `4 C/ s) t$ _; r9 T
程序14-9 计算两点距离. g* `4 a2 b% h9 n
}* V3 W3 C y2 w* H( E9 M+ O
template<CLASS T> : D) v9 a/ T7 E9 K9 c) T9 h x! l. G6 Q+ B4 k
inline float dist(const T& u, const T& v), l7 Z1 y, |8 G! p: q
( |0 f# y$ J2 b4 h7 C. P! F
{ / /计算点u 和v之间的距离9 B% q+ j3 j P* k
7 t% d; b" R9 M9 l: S- Hfloat dx = u.x-v. x ; , P+ _* S8 C' n Z2 N % @+ i2 S9 C- P5 z5 e. a( Pfloat dy = u.y-v. y ; . |! b! F/ w9 m% |9 U 3 ^2 j: r8 n! Lreturn sqrt(dx * dx + dy * dy);) r6 l- P8 e, |
* B, {8 l3 s; K* c! G& h$ l( ~* w
} ( e1 F5 a1 T1 H1 u6 e: l 4 e. E& l7 \0 i5 J如果点的数目少于两个,则函数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 ),该函数实际求解最近点对。2 \, w8 d! B4 A( j- l8 L
$ o; j1 x* z7 @
程序14-10 预处理及调用c l o s e6 H$ J, l( J% a% r% q+ Z1 \8 z! j
+ q# y& \. e. s! [3 H7 _0 c, z" T
bool closest(Point1 X[], int n, Point1& a, Point1& b, float& d)/ L( V! @ U( v" _6 X. ~8 K/ r% I- B3 d b
: }; h' }% ]6 O" t) v; F
{// 在n >= 2 个点中寻找最近点对 5 ~* Q0 h. K1 M. E$ J. R7 l % D# C: f5 P: i0 c6 P4 A// 如果少于2个点,则返回f a l s e9 N. F; \! ]' e" A& \& ^
/ V- w/ U* W2 b" _: J* l! G/ G4 I# B// 否则,在a 和b中返回距离最近的两个点 , M4 a9 `; L2 }: j( F- G: B" k ! P0 E6 R$ z/ C/ e: l& iif (n < 2) return false; 8 j9 V9 H, S W; g3 }5 {: X9 g. p: `; K- _
// 按x坐标排序 2 S, @6 K- v" I! {8 p, D( T! `- D% ]9 w9 b" o" Z8 C5 ?$ ?! a
M e r g e S o r t ( X , n ) ;6 h. h: a; S' F8 d
0 b0 W x% [$ O- e0 y' a/ L
// 创建一个按y坐标排序的点数组; H& J% W3 D# e: Q& l4 r
* r O- ^% X, o: T! P
Point2 *Y = new Point2 [n]; 0 S) U* F$ m4 C2 D% ] . E; F4 I3 w- t# _5 C& V% y. g! U6 afor (int i = 0; i < n; i++) {% Q" w! L9 N3 H
' u# @! }& ~/ p' n. m// 将点i 从X 复制到Y 3 Z. M! m4 I. D5 }6 [" A6 b$ H& c! R! U# M6 E! ^
Y.p = i; 7 s+ s7 T/ Z$ H0 A6 G) y 0 V# i% l5 d$ u `Y.x = X.x; # i/ h7 S5 R8 M! z7 y! C ( S, F! c& v7 U. I& VY.y = X.y; 2 h; t4 {- N4 [ 0 r7 }9 z& v9 C} 2 k& ^( {8 ~& ^" Q7 L% g" O8 h1 F% `9 X' _7 n9 ?. e! H. b
M e r g e S o r t ( Y,n); // 按y坐标排序 6 J. a& U9 Z' R9 \( w9 O2 u$ p7 R' q' l6 _; ]( a% C" _
// 创建临时数组2 D/ D) U/ g' \4 n" ~0 |* z. v
5 I8 S9 Z1 r$ @' |& WPoint2 *Z = new Point2 [n];/ y8 w4 |) s$ C8 g9 i
$ \% g5 N, w8 l1 Q2 h4 c9 j
// 寻找最近点对 9 r' S7 i$ c7 G! t7 f' w( V! ?# S2 u! f. k
c l o s e ( X , Y, Z , 0 , n - 1 , a , b , d ) ;4 v) M; {9 C A4 U# o) `9 u
2 L2 A: w+ ~! m1 _; a( k6 C// 删除数组并返回 7 \! I9 C4 M. z9 U: V. ^- \" w8 ^8 s. V6 t
delete [] Y;. }& V ]0 S# D( {8 R! h* @5 F( T