QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2765|回复: 0
打印 上一主题 下一主题

距离最近的点对

[复制链接]
字体大小: 正常 放大
韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2004-10-4 05:18 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
<>给定n 个点(xi,yi)(1≤i≤n),要求找出其中距离最近的两个点。( ?. _$ K, ?+ _% g- I" ]/ p! j

- L7 {2 e% Z1 x- A5 t例14-7 假设在一片金属上钻n 个大小一样的洞,如果洞太近,金属可能会断。若知道任意两个洞的最小距离,可估计金属断裂的概率。这种最小距离问题实际上也就是距离最近的点对问题。+ U; b  E8 y8 @3 z

; w3 L; v) z) u: ?4 A% s通过检查所有的n(n- 1 ) / 2对点,并计算每一对点的距离,可以找出距离最近的一对点。这种方法所需要的时间为(n2 )。我们称这种方法为直接方法。图1 4 - 1 3中给出了分而治之求解算法的伪代码。该算法对于小的问题采用直接方法求解,而对于大的问题则首先把它划分为两个较小的问题,其中一个问题(称为A)的大小为「n /2ù,另一个问题(称为B)的大小为「n /2ù。初始时,最近的点对可能属于如下三种情形之一: 1) 两点都在A中(即最近的点对落在A中);2) 两点都在B中;3) 一点在A,一点在B。假定根据这三种情况来确定最近点对,则最近点对是所有三种情况中距离最小的一对点。在第一种情况下可对A进行递归求解,而在第二种情况下可对B进行递归求解。
7 J( `  U- W* x2 s/ o* c* {& L* G
$ j7 ]) o1 N) o8 D  Z( g5 h& J  e
3 C& U* B4 T' H' Kif (n较小) {用直接法寻找最近点对
: f6 e  R5 @. Y" S/ r6 ?
7 {8 Z& J: g! ]R e t u r n ; }
! Y' a0 V  P/ R  l& d7 G3 s. f% C7 X9 d% `
// n较大* _) d" |6 P: w; e
0 B0 \9 b' y7 f8 m
将点集分成大致相等的两个部分A和B
0 n, ^) u, n7 G
6 h* D6 t: t! h0 p9 W; P1 p确定A和B中的最近点对
3 ~8 u% t- Y! t3 V0 R2 y+ i5 ?. }7 k3 i
确定一点在A中、另一点在B中的最近点对3 U5 d' l0 x2 _$ o$ f0 J

8 t  X. M' m, L2 y, v8 ]; n1 H) m从上面得到的三对点中,找出距离最小的一对点
) H2 S7 [0 Q; g) d  G# }: p8 A2 b8 T: f( ^
图14-13 寻找最近的点对. Y0 \& V* l2 D4 g% }3 r3 W: V

! y6 b+ }1 B, S6 D0 b0 t; P8 p" d2 A  z, ^( ^
为了确定第三种情况下的最近点对,需要采用一种不同的方法。这种方法取决于点集是如何被划分成A、B的。一个合理的划分方法是从xi(中间值)处划一条垂线,线左边的点属于A,线右边的点属于B。位于垂线上的点可在A和B之间分配,以便满足A、B的大小。$ K' s% X; @% A& e- L8 C6 r4 e) L6 E
7 h& D% v  g5 K& D
例2-8 考察图14-14a 中从a到n的1 4个点。这些点标绘在图14-14b 中。中点xi = 1,垂线x = 1如图14-14b 中的虚线所示。虚线左边的点(如b, c, h, n, i)属于A,右边的点(如a, e, f, j, k, l) 属于B。d, g, m 落在垂线上,可将其中两个加入A, 另一个加入B,以便A、B中包含相同的点数。假设d ,m加入A,g加入B。" p* w$ a- J" r# W$ f; R
: V% u0 O1 d* s; x: {2 S1 ^. f
设是i 的最近点对和B的最近点对中距离较小的一对点。若第三种情况下的最近点对比小。则每一个点距垂线的距离必小于,这样,就可以淘汰那些距垂线距离≥ 的点。图1 4 - 1 5中的虚线是分割线。阴影部分以分割线为中线,宽为2 。边界线及其以外的点均被淘汰掉,只有阴影中的点被保留下来,以便确定是否存在第三类点对(对应于第三种情况)其距离小于。用RA、RB 分别表示A和B中剩下的点。如果存在点对(p,q),p?A, q?B且p, q 的距离小于,则p?RA,q?RB。可以通过每次检查RA 中一个点来寻找这样的点对。假设考察RA 中的p 点,p的y 坐标为p.y,那么只需检查RB 中满足p.y- <q.y<p.y+ 的q 点,看是否存在与p 间距小于的点。在图14-16a 中给出了包含这种q 点的RB 的范围。因此,只需将RB 中位于×2 阴影内的点逐个与p 配对,以判断p 是否是距离小于的第三类点。这个×2 区域被称为是p 的比较区(comparing region)。
# c. T* q6 ?& h5 o  w4 S1 I9 f( T$ U0 o
例2-9 考察例2 - 8中的1 4个点。A中的最近点对为(b,h),其距离约为0 . 3 1 6。B中最近点对为(f, j),其距离为0 . 3,因此= 0 . 3。当考察是否存在第三类点时,除d, g, i, l, m 以外的点均被淘汰,因为它们距分割线x= 1的距离≥ 。RA ={d, i, m},RB= {g, l},由于d 和m 的比较区中没有点,只需考察i即可。i 的比较区中仅含点l。计算i 和l的距离,发现它小于,因此(i, l) 是最近的点对。
4 V; R' k# g7 e; ~: S$ F$ Z  a7 K8 L  n/ E# \
为了确定一个距离更小的第三类点,RA 中的每个点最多只需和RB 中的6个点比较,如图1 4 - 1 6所示。% O3 B$ m5 c# Y9 j0 u
  I6 O3 I8 }( `8 p
1. 选择数据结构
4 Q4 b3 ~. J7 m# j; |
% s% V0 Z$ e9 m% a3 s$ |. |* i为了实现图1 4 - 1 3的分而治之算法,需要确定什么是“小问题”以及如何表示点。由于集合中少于两点时不存在最近点对,因此必须保证分解过程不会产生少于两点的点集。如果将少于四点的点集做为“小问题”,就可以避免产生少于两点的点集。3 w; K2 q# r$ d9 \
2 k# v& w$ O  }; y9 q
每个点可有三个参数:标号, x 坐标,y 坐标。假设标号为整数,每个点可用P o i n t l类(见程序1 4 - 8)来表示。为了便于按x 坐标对各个点排序,可重载操作符<=。归并排序程序如1 4 -3所示。9 N0 H* H: D4 }* R* i
4 [: T$ W0 \: O
程序14-8 点类
/ o, `$ S/ y! a" p5 W/ L0 ]% \7 b( K  e) C8 Z% {3 X
class Point1 {4 O$ E1 L3 ?% r1 Q! G
8 }& N9 V) v) g$ D! ~. y0 G. ~( r$ g; m
friend float dist(const Point1&amp;, const Point1&amp;);
) o2 k3 d7 \4 t" P2 c4 t1 }' B. |: y1 f- ~+ Z+ y
friend void close(Point1 *, Point2 *, Point2 *, int, int, Point1&amp;, Point1&amp;, float&amp;);
  h+ b. z) L9 s/ V5 E5 T; Z5 G& ?6 \. s
friend bool closest(Point1 *, int, Point1&amp;, Point1&amp;,float&amp;);# O( o* q  J' X9 m

& t% ^6 [* u  o( Tfriend void main();
0 a- X0 Q/ o& R( A1 V) |( B" t. |8 j0 w0 Y
p u b l i c :
1 V, W% Q$ ]. Q9 Y( m3 X/ ]" J% \# B, y: Z  z# k/ B
int operator&lt;=(Point1 a) const
. p4 v& |& f9 H! T8 B2 Y9 P* F* E% \0 h
{return (x &lt;= a.x);}
$ y; D- i+ l, O( ~4 m  C! u" F8 ]1 d7 E- r: |; U4 Y
p r i v a t e :' h9 ^* L) e8 e8 J2 }9 A( r& F

6 E( {* S" Y3 R8 \int ID; // 点的编号
+ O! c5 `2 _4 ~, b! b! M+ F, F# L$ ?8 M& W8 f
float x, y; // 点坐标
/ l) X# M& O3 `. k, u/ ~7 e0 t  |3 d2 Q  S4 z1 ~* }$ f" x
} ;
+ _% W  Q8 @0 J" z5 t: N8 E! }! O: c! D" \9 a) _) K
class Point2 {7 y: B1 O' B/ ~* W5 h4 M; k! G
+ d! x3 ^1 h9 c9 [1 |* R9 E
friend float dist(const Point2&amp;, const Point2&amp;);& J- k0 e+ v7 F2 H8 Z

! o( X1 Q9 S# P' N7 e2 q. Kfriend void close(Point1 *, Point2 *, Point2 *, int, int, Point1&amp;, Point1&amp;, float&amp;);
3 w8 I; K8 Z: i- ?5 P$ l# W# M6 u/ [1 i. k
friend bool closest(Point1 *, int, Point1&amp;, Point1&amp;, float&amp;);9 o$ [& J3 N# V0 T
% p) Y3 R1 m+ `! i8 X" I) f- Z
friend void main();* @) f  f. l7 \+ O
4 O7 e/ Q3 n8 b5 w, |; k  _3 C) C
p u b l i c :
- ^* k/ _; L1 |' X. f/ b5 K1 q/ O. T# h: q1 r
int operator&lt;=(Point2 a) const
9 w7 t) t0 T4 z1 U, H7 I- Y5 Z4 _* B7 q; J" {7 q( k! |
{return (y &lt;= a.y);}
% w( V6 v, U4 U! i
9 u2 E# J& p/ ~* v$ l( ?! Up r i v a t e :$ @$ [6 q# ^5 u" r+ K% r3 d1 b9 Y
" T" s! `1 A3 Q0 G7 s  a
int p; // 数组X中相同点的索引
7 D; i. U( B3 N! V$ f, L1 o, a% e8 i# h
float x, y; // 点坐标! s$ U) [( f* i2 e2 h/ j1 [

. ~2 U- k  W8 {, F1 i} ;" A6 B4 U1 ^$ [) M- L1 A

- @: u6 }+ X1 \: s) t所输入的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中的对应点。
& g; @, T' z/ w1 w2 j- I; G: z( Y1 G+ e* Z5 d6 t& x/ I) [7 b
确定了必要的数据结构之后,再来看看所要产生的代码。首先定义一个模板函数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类的友元。' e9 H* X2 i4 ^8 I) z! H

$ A2 e# ~6 k& w+ L3 |2 E+ f8 g3 B程序14-9 计算两点距离
6 v, u! e9 U7 X# d! k+ ~& j7 X% k$ y4 d' T
template<CLASS T>/ M" A+ a' X5 [  g: ~! \) C

. l7 J8 r( g, tinline float dist(const T&amp; u, const T&amp; v)
, A1 m/ [! L3 I- V" v* y8 Z: ^& }! \3 q: s: s. I& Q# |
{ / /计算点u 和v之间的距离
- r# G* {, ^6 S/ M9 O4 w3 N1 I  i8 ^* l! ^5 O/ x- O# m4 O, R- w0 z4 E
float dx = u.x-v. x ;% B( j+ l4 k( c9 N( \: e

3 y# N6 j  z  z& xfloat dy = u.y-v. y ;
, X3 H. R- c! @/ v6 Z% O: L' b; z! x, i3 b
return sqrt(dx * dx + dy * dy);
" J5 v* t7 W) N% ~4 x- O( P+ y( u7 u# n/ `" Q* l9 I0 B7 y
}& w" Y2 [, D7 o% M

8 j" O3 p' ]; p6 R! y- E如果点的数目少于两个,则函数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 ),该函数实际求解最近点对。
" W" _# B% Q6 f# @6 ~: L* [. }
( e& E6 I; I1 r2 A+ E程序14-10 预处理及调用c l o s e6 O3 W8 ~# F$ f" Y) ~5 J! E

. d9 j. p' I0 u- k  L% @/ W! x+ Vbool closest(Point1 X[], int n, Point1&amp; a, Point1&amp; b, float&amp; d)
  S' @' _6 Z. L5 w0 E4 E; S7 h9 M8 k7 P( P8 Q; o$ j! [4 P
{// 在n &gt;= 2 个点中寻找最近点对) S: @2 [3 Q1 N" K
  Q. Z' [+ J$ W" C
// 如果少于2个点,则返回f a l s e& z% O6 F6 U( K6 c1 h

' F2 g' [! l2 g/ _( q// 否则,在a 和b中返回距离最近的两个点- {. l& y% S+ d! w7 ]7 o7 d
% L, v2 M' ^  |) i, J
if (n &lt; 2) return false;9 K: R. I: `. v4 `6 R1 i
2 w2 K) L& _1 R" Z0 X" T
// 按x坐标排序1 u& u6 D% _9 ~' E

  q% L. S( j% ]M e r g e S o r t ( X , n ) ;
4 y3 B& A0 E7 k5 y
- ?8 a9 o4 p, Y( H( H// 创建一个按y坐标排序的点数组; R& M% [' S5 Z, T- \) y' \

# E9 }+ C. X8 wPoint2 *Y = new Point2 [n];
4 u  r7 c+ S* \0 G
0 r! X" Z3 m! v. |for (int i = 0; i &lt; n; i++) {/ m. y, K' G& F* [/ |3 P. T, Z" u/ n% @

1 s3 x' E+ B  e// 将点i 从X 复制到Y# L; T2 @' H* Z
- E5 D7 {- L. D3 L, x
Y.p = i;
) @8 M6 z' f* X6 }
" \, \% x+ g! P% [Y.x = X.x;
2 ~3 d" d; q$ P$ \& p
8 B. p. ^5 j1 {/ y: A8 w+ F- b; ZY.y = X.y;
* Q1 H2 e! K; U, ]& `8 c/ r. L
- d& m9 @- k- ~# ~: _' r}
) d# P$ Z  m% \' }2 b5 a. G& L4 V$ v
M e r g e S o r t ( Y,n); // 按y坐标排序
! Q) p8 t/ T. \( O3 o1 Q- w2 m
9 l! m' l* d; ^; {5 U+ j1 W( u& p// 创建临时数组: ]6 O1 v. W, T4 K
7 y) [/ W6 L; d3 A
Point2 *Z = new Point2 [n];
# V1 y1 s* a4 I; }; p* p4 r
% O) v2 ^& l) U! m// 寻找最近点对8 [+ z# x# E( Q8 G
) A) H, f6 h6 N# a- G5 I8 I2 \
c l o s e ( X , Y, Z , 0 , n - 1 , a , b , d ) ;
7 p0 H( P4 ^' n7 m  g# U5 I
" R0 U. W" Y/ c+ s// 删除数组并返回
3 X) j+ z5 n; X4 {8 N+ P- H" e' h8 G$ F
delete [] Y;
  u( T9 n2 I3 g" d8 K+ `$ u. h3 @! ~  n; p2 ~1 D
delete [] Z;9 K0 z- ^) N# B4 y# @
8 P7 z4 y' Z( J3 Z3 A$ h  I, G' x% ]
return true;' Z! ~, D, f7 K: Z$ T8 Y. U

5 f, k  i) }/ w5 g}
4 U1 O7 a; n+ g* w; ]# }  |5 K9 I. ]7 j$ j# b4 z
程序1 4 - 11 计算最近点对
0 |% r- W9 p; ^( e: ?  \5 W! G( u8 x' ~# Q* B
void close(Point1 X[], Point2 Y[], Point2 Z[], int l, int r, Point1&amp; a, Point1&amp; b, float&amp; d)
1 S) j; c7 l8 J  w  L4 b2 Q$ A  B# B# a! B$ y
{//X[l:r] 按x坐标排序
9 l* p1 C; Q. |% L) m8 ?! Y+ J/ d6 Q1 @- \. Y# W( Q; W
//Y[l:r] 按y坐标排序1 ^+ @& P- u" k& V! V7 v; @0 U
3 P- `  B" ~, _9 e. U  H  }
if (r-l == 1) {// 两个点
8 J" h; R" a- J; j+ v( t8 I: L$ o  _5 P: y/ S; \0 O- X
a = X[l];
8 P/ f7 A8 D0 K. R
: k6 ]* Q; I* ub = X[r];
% K, p6 h. f  L. V0 ]- i# D6 |; x- V5 v; J
d = dist(X[l], X[r]);
3 [3 t% V! X1 c% P! `+ p) @/ G8 ~4 t6 K9 J$ q8 u
r e t u r n ; }! ^8 B; J7 O$ G7 p/ C

) j8 o5 [1 S( ^& `4 x9 k3 Jif (r-l == 2) {// 三个点
8 S( r" y) D" X. _; @) c3 q: E' u5 |* i# e' ]8 T8 O) u2 v1 [9 J
// 计算所有点对之间的距离, E0 R6 x" e% `, f. V: w/ S
, B# n7 v3 z  h! S
float d1 = dist(X[l], X[l+1]);
  g% l0 k% T5 E* ]
/ a8 S7 V8 o& `  i' D: V. }float d2 = dist(X[l+1], X[r]);
4 d( k- Z. V9 f. W! A& K5 s1 N' Z- K/ L: J; k9 m; r& `
float d3 = dist(X[l], X[r]);
: s$ _/ X* p* l
  S, V4 [* j+ M9 X// 寻找最近点对
& k3 R5 K* u# N  u. o! s
0 l2 L1 f7 }# x/ f; @if (d1 &lt;= d2 &amp;&amp; d1 &lt;= d3) {
" X. O: H8 K, b" {- c9 g4 G4 B2 \4 f4 s
a = X[l];1 W4 P  h2 n: a# @1 r9 b$ A& ]# _
% J, v& f3 E- M* G
b = X[l+1];, n8 J) t6 P& _! O) @
& p/ C# D, s3 N
d = d1;7 @; X7 `" n* ^3 r

& m* B  C# R2 [1 [8 Z! ~r e t u r n ; }
2 K* X' K: k( X) n/ H' W
* t, v/ M* h( w! Uif (d2 &lt;= d3) {a = X[l+1];+ q; l+ U) G8 Y* O& E

: R$ d, n% g4 h  k* f; }! z2 hb = X[r];+ E  Y9 H5 F( ?/ P/ k/ t' [
7 f5 j( d1 X% a2 ~& E% ^! J( T6 I
d = d2;}
' M9 G8 ~" k; R2 I5 z5 o% a" m$ w5 g4 V1 P: m
else {a = X[l];; S8 A+ o5 x5 e# D
( l9 G1 n6 [5 O4 ^' T) ]: T; o) c  g
b = X[r];$ F3 l* j/ r0 R% ]4 _

5 h8 H3 e* W6 A" b- Jd = d3;}6 {. k1 n5 l+ a$ g3 u2 A
) _2 K7 E* M1 A) k3 t
r e t u r n ; }4 a% m' S7 U+ ~3 p7 ^
; t8 {, Y% m' O: y5 @8 [- k5 p7 l" A
/ /多于三个点,划分为两部分3 V0 e3 i( ?! ?. e" ~) Q
7 G% s/ g$ j% w3 j7 s) Z" j
int m = (l+r)/2; // X[l:m] 在A中,余下的在B中1 Q. x+ U9 Y1 J( `, d; t8 m, ~9 y
" _: e' J7 L8 }0 V
// 在Z[l:m] 和Z [ m + 1 : r ]中创建按y排序的表
, A" K$ x- p9 }+ O8 I8 {+ I7 i0 m# e
0 p# ^+ v% f: `1 n& u" Z) Uint f = l, // Z[l:m]的游标( r( l% c, ]3 b0 G# Y- ?1 k+ ~

" Q" W- q) C: m' a$ Bg = m+1; // Z[m+1:r]的游标
6 m7 n& T6 t* G, B# \' l
' t% \, \3 E8 P3 T; P' Rfor (int i = l; i &lt;= r; i++)) S- O. }; Y* V% g  B

: l5 V8 A( Q2 {2 f' K' oif (Y.p &gt; m) Z[g++] = Y;: K+ ?% S+ h: I! k! m2 |
3 {6 i! {9 a0 a: J
else Z[f++] = Y;, P2 N# v9 l6 b( ]% G, U) ~: s( U

0 p' z. Z5 c  B( ^/ R" h// 对以上两个部分进行求解& F) L& j) p6 r- y3 D
6 J6 U# s- i1 K$ z
c l o s e ( X , Z , Y, l , m , a , b , d ) ;( `+ w, F/ `1 t4 d. s2 r0 d2 v2 W
. D( Y- u8 X3 R2 u' s; w& D( c# s, S
float dr;
$ @  H8 e1 M7 W$ I- @- v; v% y: r2 m# T
Point1 ar, br;9 ?) c( f7 V) U/ [/ j4 v
7 U! d; I& ~8 m* Q4 @. |; }
c l o s e ( X , Z , Y, m + 1 , r, a r, b r, d r ) ;
' z) E/ \* b! x( m& m! s. K/ |9 l, T8 V) L5 Y# t# {/ f
// (a,b) 是两者中较近的点对
5 ]7 G  D) x" @$ c+ o& W$ S. E3 ^  k; t7 s& k. y
if (dr &lt; d) {a = ar;/ A+ _* t( Z4 H+ {8 j' J' s
$ t. F3 Z% V' `1 c& a# j; k0 M* L3 D
b = br;
. O: {5 B) v, L! t( y1 `$ C/ P. s0 a1 Z& I* }1 r% ]3 w6 j
d = dr;}1 u' u/ @" {* c0 \" D

! k( H# K  j- ]0 p* ]* SM e r g e ( Z , Y,l,m,r);// 重构Y
4 h9 Z% p+ \& U3 J+ ~: w4 h9 b6 h$ |5 {2 S- h3 ]& r; z
/ /距离小于d的点放入Z
0 H# D9 K/ g  Q) I: N# ^" s* m3 w
4 h) W  `& J. H  Q; z* w' l! kint k = l; // Z的游标! \6 r$ r1 l! h- ]
: ?# K  m! k( x6 R) `
for (i = l; i &lt;= r; i++)
4 K" Y+ V8 M! q2 B4 a8 Y3 a+ w. {3 Y; i
if (fabs(Y[m].x - Y.x) &lt; d) Z[k++] = Y;7 b! j. _) N& S( T
: L: p9 z8 k/ i$ [
// 通过检查Z [ l : k - 1 ]中的所有点对,寻找较近的点对
2 E! k! i' k& ^  l& ~+ y/ A$ `
: @5 r: d* ?% f. Gfor (i = l; i &lt; k; i++){! y5 {" Y+ w+ }5 R7 V  Q5 F% [/ b

% v1 b7 S$ V6 \9 j. h  d# Pfor (int j = i+1; j &lt; k &amp;&amp; Z[j].y - Z.y &lt; d;
& Z& w) j3 d; @" L0 R/ h
2 s$ {# v& s. C1 Gj + + ) {
- E7 P) L  e0 k, B* c9 f
. P0 `3 A, Z8 l8 w; \8 qfloat dp = dist(Z, Z[j]);
* S8 t2 Q8 A2 h$ W% E2 T$ b
7 f2 e0 `  y0 G4 b1 m6 R/ H/ Tif (dp &lt; d) {// 较近的点对
8 G+ |" p0 c0 d  O8 _4 x; U* c% N5 b' Q3 e
d = dp;
5 X6 k4 b* h0 P# W
* R* ~2 X/ M* @8 k/ k& e- i* P: g; u  Ja = X[Z.p];
/ }" N/ x. Q1 L0 T
1 h; X0 M+ [" N% C9 q3 J# Ib = X[Z[j].p];}
. [5 [0 r; G/ d& l8 P6 e+ v9 F5 E- u
}; L1 A6 k( K9 o5 J

% l8 r0 U8 B/ i1 U8 s" M}4 R3 g: B. d( v, A. k: F, ?
% o8 v) x1 _) `/ E& @  p
}
! F, U9 b1 X4 C
& u+ F6 K& |/ `9 M: c* a8 @函数c l o s e(见程序1 4 - 11)用来确定X[1:r] 中的最近点对。假定这些点按x 坐标排序。在Y [ 1 : r ]中对这些点按y 坐标排序。Z[ 1 : r ]用来存放中间结果。找到最近点对以后,将在a, b中返回最近点对,在d 中返回距离,数组Y被恢复为输入状态。函数并未修改数组X。" W1 b3 d) B# {( q* M  u; K9 {
/ \) J8 f" l, f% ~" }- R0 T' d. c8 q8 |' T
首先考察“小问题”,即少于四个点的点集。因为分割过程不会产生少于两点的数组,因此只需要处理两点和三点的情形。对于这两种情形,可以尝试所有的可能性。当点数超过三个时,通过计算m = ( 1 + r ) / 2把点集分为两组A和B,X [ 1 : m ]属于A,X [ m + 1 : r ]属于B。通过从左至右扫描Y中的点以及确定哪些点属于A,哪些点属于B,可以创建分别与A组和B组对应的,按y 坐标排序的Z [ 1 : m ]和Z [ m + 1 : r ]。此时Y和Z的角色互相交换,依次执行两个递归调用来获取A和B中的最近点对。在两次递归调用返回后,必须保证Z不发生改变,但对Y则无此要求。不过,仅Y [ l : r ]可能会发生改变。通过合并操作(见程序1 4 - 5)可以以Z [ 1 : r ]重构Y [ 1 : r ]。
3 K' x& l) \# {5 \6 N) g. `" n
; h% I4 x1 ^9 ?$ |7 I) B6 j* G为实现图1 4 - 1 6的策略,首先扫描Y [ 1 : r ],并收集距分割线小于的点,将这些点存放在Z [ 1 : k - 1 ]中。可按如下两种方式来把RA中点p 与p 的比较区内的所有点进行配对:1) 与RB 中y 坐标≥p.y 的点配对;2) 与y 坐标≤p.y 的点配对。这可以通过将每个点Z [ i ](1≤i &lt; k,不管该点是在RA- V0 d+ z8 q9 a+ w$ U8 F! u- L

7 \1 h+ r" M, e8 [% E) |0 R" u还是在RB中)与Z[j] 配对来实现,其中i<j 且Z [ j ] . y - Z [ i ] . y< 。对每一个Z [ i ],在2 × 区域内所检查的点如图1 4 - 1 7所示。由于在每个2 × 子区域内的点至少相距。因此每一个子区域中的点数不会超过四个,所以与Z [ i ]配对的点Z [ j ]最多有七个。
' M4 v5 _' g9 R; v: B4 V- i
( F% u% V% Y& ?6 f* c9 F# ]6 G+ c$ j2. 复杂性分析
% k; E9 |# x1 P$ g0 w/ X. J5 {7 f2 R0 r: _6 P
令t (n) 代表处理n 个点时,函数close 所需要的时间。当n<4时,t (n) 等于某个常数d。当n≥4时,需花费(n) 时间来完成以下工作:将点集划分为两个部分,两次递归调用后重构Y,淘汰距分割线很远的点,寻找更好的第三类点对。两次递归调用需分别耗时t (「n /2ù」和t (?n /2?).# t2 g6 A' c1 T+ C

+ ]2 Q2 r5 v/ |% H. P这个递归式与归并排序的递归式完全一样,其结果为t (n) = (nl o gn)。另外,函数c l o s e s t还需耗时(nl o gn)来完成如下额外工作:对X进行排序,创建Y和Z,对Y进行排序。因此分而治之最近点对求解算法的时间复杂性为(nl o gn)。</P>
zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2026-4-20 09:55 , Processed in 0.433628 second(s), 52 queries .

回顶部