QQ登录

只需要一步,快速开始

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

距离最近的点对

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2004-10-4 05:18 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
<>给定n 个点(xi,yi)(1≤i≤n),要求找出其中距离最近的两个点。
1 s3 h. j% ]+ A9 G& z' l
6 ^; D, j% R; ?( Y例14-7 假设在一片金属上钻n 个大小一样的洞,如果洞太近,金属可能会断。若知道任意两个洞的最小距离,可估计金属断裂的概率。这种最小距离问题实际上也就是距离最近的点对问题。
, p2 ~8 T. y" p
% g& R! y# ~6 X; J9 }通过检查所有的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进行递归求解。
1 V4 P- {+ B9 u
/ i6 k$ n. @* F* [8 L
; T0 O/ Y$ I* X% A8 Yif (n较小) {用直接法寻找最近点对
2 Q6 f, T( }  Q/ {8 `0 z- h
7 k) D. _% T! }4 rR e t u r n ; }7 `% B& ]+ B" e) n+ X2 K5 o3 v

- V/ I: t- O/ V  ]$ p// n较大0 U& n, S1 B/ E5 P; r

1 T: s3 W6 E- v! w* I将点集分成大致相等的两个部分A和B
3 v  `) X0 w1 X) c) N; p6 a
  u! q- D* z8 O& A确定A和B中的最近点对: o4 n- n" e* n- s' ]

4 B, [8 p5 o! @2 ^" P确定一点在A中、另一点在B中的最近点对& k- \) B* m' F) `4 c
- K, p  Y0 K& ^+ T, K- {
从上面得到的三对点中,找出距离最小的一对点
% C4 `& r5 l) _0 ?+ [4 I2 O
% o$ i& b8 ?# ]% n  d5 T+ e* @0 c图14-13 寻找最近的点对+ J3 C5 I4 T) @; y' x2 f

0 R: q2 j, b2 e9 k+ y; K
6 E. l9 |7 v2 O- j& e$ u7 ?. x为了确定第三种情况下的最近点对,需要采用一种不同的方法。这种方法取决于点集是如何被划分成A、B的。一个合理的划分方法是从xi(中间值)处划一条垂线,线左边的点属于A,线右边的点属于B。位于垂线上的点可在A和B之间分配,以便满足A、B的大小。/ z5 r& j) c( k
+ F$ F9 A5 w8 G+ y$ f
例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。/ s. x, M! A( o6 {

+ r4 v# U( o6 U8 S% K设是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)。4 K+ J6 @; W+ R5 Y

, W% Y" h) p; ~+ q8 z5 E例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) 是最近的点对。
1 o' Z' h) j1 N2 {) \! f% u
0 n& s$ }1 r! Y6 ^  Q" S为了确定一个距离更小的第三类点,RA 中的每个点最多只需和RB 中的6个点比较,如图1 4 - 1 6所示。
. K6 H4 k2 W6 p, G! g5 T8 ]8 _5 H
3 N# C9 y7 x9 y. e2 c1. 选择数据结构
( [( Y& v/ y- @( Z( [1 |
, q/ o2 G* g( }- H为了实现图1 4 - 1 3的分而治之算法,需要确定什么是“小问题”以及如何表示点。由于集合中少于两点时不存在最近点对,因此必须保证分解过程不会产生少于两点的点集。如果将少于四点的点集做为“小问题”,就可以避免产生少于两点的点集。
$ ^, z1 E' \' e: Z: ~0 g
2 E7 y0 K. U) x3 R每个点可有三个参数:标号, x 坐标,y 坐标。假设标号为整数,每个点可用P o i n t l类(见程序1 4 - 8)来表示。为了便于按x 坐标对各个点排序,可重载操作符<=。归并排序程序如1 4 -3所示。. P9 N+ |" s+ K" N

, U, d" ^  I' `4 ~7 k程序14-8 点类6 _" b3 E' O3 H( C, c1 g# C0 L
: z2 p! a3 q- g: |7 J( j
class Point1 {
4 q) x* F3 X' ?" Y, J# K9 D" i1 b; T" \+ i0 @$ N6 f/ f( d
friend float dist(const Point1&amp;, const Point1&amp;);
' g. B4 p+ G8 p! b; @( {
/ u" M3 P6 G: e+ u$ ^6 f  Cfriend void close(Point1 *, Point2 *, Point2 *, int, int, Point1&amp;, Point1&amp;, float&amp;);+ h' p" Q3 k' m4 f+ T3 A
5 `* b  U/ n3 r& |6 T6 u4 t' o" O% [
friend bool closest(Point1 *, int, Point1&amp;, Point1&amp;,float&amp;);. \! v- G' z- j1 |8 a0 z8 m
) m+ B. Z& x2 F6 l( |9 r' B
friend void main();  m+ O) s' _. K( B" b8 z

- @" i) E4 H. l6 Pp u b l i c :' d% D7 @% I0 z( a% v0 L, m

+ b, _7 l' \" V9 J/ |1 V2 a- p" Xint operator&lt;=(Point1 a) const
, K! V9 l3 r7 g- O7 o! v; F  [7 i9 \6 V. C  A
{return (x &lt;= a.x);}2 B( |, W6 u% r* p* Y3 e* e

& T% Q2 r/ S! X, h  @9 [p r i v a t e :
& m' N/ t* v+ |; Y  V+ n; @4 ]% i8 S6 g( a
int ID; // 点的编号4 K9 b# N, v5 D# P7 r
+ M7 ~; M  }5 U5 g6 Z" _: C* [
float x, y; // 点坐标6 {$ n- w3 `8 T0 f

) H& C! ?, N' S, V! N3 y; v; e} ;! ^1 M! l% p! P2 @; m' u
, W9 z. E8 T2 ~5 d( q: O$ S& i
class Point2 {
- K1 Q9 _3 P+ [' s; q2 w- o7 S& ~$ E2 ~
friend float dist(const Point2&amp;, const Point2&amp;);+ \5 _# v6 n: s1 f) d( t% O" Q
7 P! h# M( A# R; b
friend void close(Point1 *, Point2 *, Point2 *, int, int, Point1&amp;, Point1&amp;, float&amp;);9 a* r! K3 M7 a. `1 Z! E

) h$ J# `' |! E: Y1 ffriend bool closest(Point1 *, int, Point1&amp;, Point1&amp;, float&amp;);
( C# j, k  r9 c6 P# u0 b8 k3 \+ g: c- X" k( G
friend void main();
! G2 O$ _3 J0 @$ ?- I  K. B* S; z% z8 O; h
p u b l i c :
( U" P7 D6 a: ]9 `; B  i; A& a
int operator&lt;=(Point2 a) const
$ D  X, ]! j& D4 D1 y: ?8 @9 P6 W# G* j3 O& N- B
{return (y &lt;= a.y);}" Z% {% F/ }' Y, G

& |# d7 m; V+ P# C* [. D( Tp r i v a t e :1 u3 a" }; X5 M6 Y4 H

; S& w4 N# n# l: v( I! p; cint p; // 数组X中相同点的索引
! }: s2 j+ d! p" r, `8 ~0 h) R8 `7 f' E: ]+ K, \5 \% b8 b
float x, y; // 点坐标# i) O/ M' [" V" q# ?" w# A6 u

( ?7 x& T1 {" S) c  ^6 |} ;
5 j6 M) t( S( \) r, r+ o8 q8 L0 _7 q! f0 b! c9 |+ P( d' P
所输入的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中的对应点。  K; u6 q2 F+ `4 i; \. t- x
) B# g" ?6 U+ ?0 z4 Q$ O/ K
确定了必要的数据结构之后,再来看看所要产生的代码。首先定义一个模板函数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类的友元。
4 d( i6 H. ~4 x) b& L- |  N  o5 p& V4 F7 a. S( {
程序14-9 计算两点距离  c+ y" Z2 t( q% `4 C( t

& c) u6 y9 J6 L+ Ktemplate<CLASS T>" X, q9 S' [) D: R8 [/ a- O
" L# j: `0 w3 ?
inline float dist(const T&amp; u, const T&amp; v)
+ Z8 `1 C$ L7 t9 B" V. Z6 a7 l0 a  z, i) N
{ / /计算点u 和v之间的距离
, _, y" e' j2 g+ u
% d! S3 ^! Y  S( Mfloat dx = u.x-v. x ;
! b0 W+ Y, C1 d& Q9 Y2 p
& U8 W/ ]6 h- _+ n+ C3 Jfloat dy = u.y-v. y ;5 m, A+ O3 ]. b- a2 Y

; l6 }! W3 D3 L( ~$ @0 k6 Zreturn sqrt(dx * dx + dy * dy);+ h# Y. T; [( z  k3 r4 I

5 c! L2 t6 |2 B$ G2 }}4 o& Z9 |  F2 f; [: D4 V, v+ O

9 O4 n6 h  i+ |- j9 g. J7 l如果点的数目少于两个,则函数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 ),该函数实际求解最近点对。0 W  O; n% A! Q5 k0 j- J

4 W6 }, m3 R% E9 `' A  _/ e7 [程序14-10 预处理及调用c l o s e
; p/ P# H% e/ F" U# m
7 n# p/ ^0 ]* Z, D$ G- W, f8 V5 abool closest(Point1 X[], int n, Point1&amp; a, Point1&amp; b, float&amp; d)
2 e) _# v" U( \5 D
! {% Y0 p8 {- r, ~" D4 }+ P& ^8 i{// 在n &gt;= 2 个点中寻找最近点对
/ H1 y5 {5 h+ Q9 D! X
/ C* d% L6 s6 M8 K) t// 如果少于2个点,则返回f a l s e- E/ O1 b; m: k; q
$ N% G' T6 |: d. I4 ^
// 否则,在a 和b中返回距离最近的两个点, [6 \" T! B# S* F/ A6 `0 C, P
. t( B' K9 J& W1 Y
if (n &lt; 2) return false;8 L) p5 T! _+ ^  t0 n

% F  ^9 W8 Z  [3 s3 b// 按x坐标排序
! ^( m* @3 p# m& ^" v
" \$ S  P  }0 @, ^& U7 c0 ]+ [8 {M e r g e S o r t ( X , n ) ;
( W6 H5 T* K; @
1 b* H8 e. b. q" i: x) n, J// 创建一个按y坐标排序的点数组
# c: G$ F4 C: `' o/ W; `
) V4 D( C. N! p0 y+ }" cPoint2 *Y = new Point2 [n];3 u' A, P  d2 b2 L
3 |* T- J8 E% C. [/ s! N
for (int i = 0; i &lt; n; i++) {! c8 M* Q6 W( z. }
: K1 K1 t  {0 J) h
// 将点i 从X 复制到Y. i0 {3 B3 D6 Q2 u; J1 Q$ C
5 v! R4 C- L. @$ }
Y.p = i;
' J! c9 F0 c/ e. ^' L) R1 U! g
1 R* D; q8 Q6 p9 B1 [7 WY.x = X.x;2 d. F$ K: F9 T! y+ N! q+ z$ i
, p/ ~9 A5 k9 v4 N; T" g7 o+ ]8 H& ?
Y.y = X.y;
. W. @" \4 A4 R: Q7 P" m3 u6 A2 ]1 L
}
8 V* |$ P2 z" Q! Z+ K( y: C; V. B+ [5 n; A* q4 b& L+ b2 y8 I5 }
M e r g e S o r t ( Y,n); // 按y坐标排序
! f' r4 [, e  @; |* Z
! M+ t/ J* \8 t// 创建临时数组4 J* k$ r# ~# B! q9 X

" h# k- R! t& R# S  yPoint2 *Z = new Point2 [n];
6 k) J0 o- }! a; D: A4 ]( U" i4 [% R0 N' x9 h8 f* A# s# X/ f
// 寻找最近点对
8 u3 O: J6 Q) F+ S" v" V8 w7 c( K/ R$ O
2 o; K# w( O6 x' W" _$ rc l o s e ( X , Y, Z , 0 , n - 1 , a , b , d ) ;
, X: {' j, {7 V6 x! D
8 L) d7 x2 g$ D1 h// 删除数组并返回0 m  g6 v* f2 i) F/ Z" g( r2 G' _

& b+ s. t8 Z" N- W4 }4 Edelete [] Y;3 \! U  j# k; |8 z

. D) q2 K3 F8 X3 B, Mdelete [] Z;
5 w9 `. d0 {6 E* A$ q7 K
2 `  h- Z0 R: ^return true;2 R- c0 S7 K# A* N/ X. b( D* w. }+ i) g
7 s1 D# X4 H# m9 b* `
}) @7 K/ w% \# X+ M8 t

( Y3 n5 `1 R, ]5 D3 T9 [程序1 4 - 11 计算最近点对
+ ?* y. v5 O+ K/ W1 W
1 e  t* ]6 j9 Bvoid close(Point1 X[], Point2 Y[], Point2 Z[], int l, int r, Point1&amp; a, Point1&amp; b, float&amp; d)  x3 H0 R, M9 e- u3 R9 Q1 W3 I+ [
: ^: V1 J* Y0 d. n; w6 M1 B3 X
{//X[l:r] 按x坐标排序
3 k7 {6 U6 h! x$ B! m3 o, {& c5 e* f+ o+ P" [  G
//Y[l:r] 按y坐标排序4 C0 L& ]4 k/ w5 g2 C
. f& d0 ?0 ^  q! n
if (r-l == 1) {// 两个点
4 _$ Q1 W7 n4 ?& x. w- w0 z& g  a5 e
, s  X3 b1 S! b  b9 A' a' Ua = X[l];6 k! C9 |1 E  I8 ?- ~. G9 c% n
# r7 |  a7 [% a; Z
b = X[r];$ h) r6 O% `9 T9 \

7 s$ y# s' u: B4 R- m3 P# C( d* dd = dist(X[l], X[r]);
7 `+ ^* n0 h$ @4 n
# z. B9 m) `. {& |; Vr e t u r n ; }, u1 u% i5 C2 z: M7 k
; h, v4 s# F+ f- \
if (r-l == 2) {// 三个点1 K  t, ?% }4 K$ z; Y9 F2 [

+ E& R# ]: N' |$ M' @) w! D& E0 n$ I// 计算所有点对之间的距离
. `2 L3 ]1 ~# N( U/ F! N& o; ~' o5 P& e; @  y
float d1 = dist(X[l], X[l+1]);
/ D; r$ J  s5 `/ W. Z/ z
' {2 y! s' h- B% }2 hfloat d2 = dist(X[l+1], X[r]);
( _( @: \7 ~; ?. v8 @$ L1 Y" u; I. ^
float d3 = dist(X[l], X[r]);! O2 j( v7 A" a4 v8 e  S, ]
$ D- V% B1 u7 X9 N2 K. h0 c
// 寻找最近点对4 Q6 u1 b- \1 |6 X

5 b' o# g$ I, v- o; ^4 qif (d1 &lt;= d2 &amp;&amp; d1 &lt;= d3) {
9 D( ?! ^; i1 F( }2 G
, h) a% J3 ?- sa = X[l];
, o' u% g, L- Y7 d: G2 y8 M- L. R( k
3 \# i7 B0 z4 _& ?b = X[l+1];6 J, l5 A( T4 a4 o9 J* _; r
, @! m. s5 g& U6 x3 ^7 |" e) T9 J+ Z& s
d = d1;2 u, O5 R  g% J0 l+ \8 [
; M% @# y0 O7 j; B" `  r. j
r e t u r n ; }
: N. d0 ?: f$ C. f6 ~! ?+ W  @& R0 \- Z3 G+ N' [
if (d2 &lt;= d3) {a = X[l+1];
. d  y( Z7 J. Q; t8 n" P. W' v8 j9 u3 {6 N- b
b = X[r];
" J; O3 V; \. H, l: |! [& O, J% D% h8 L5 y& h) e, c" ?
d = d2;}
4 e( y! |, c7 u( U( W6 r
; K, k! Z7 t' \9 Y; S' M- \' Z2 Xelse {a = X[l];
' J6 J  D1 ]% u7 {/ L
' b4 J- T7 K! Y  l# q! M1 {b = X[r];6 u4 X& O7 q- |
+ X/ y6 [2 l& T0 `9 ~0 ]. V8 B
d = d3;}
7 q; k1 q4 h7 o
( ^' j. S) d+ l- v8 d- xr e t u r n ; }4 j( h2 }, T/ c$ R) Y9 r

3 f* K# Q+ V: ?) K+ M" h/ /多于三个点,划分为两部分
% X$ W! ]' ~. k8 |% h! e8 ]4 S  h
' H" B; s. E6 C. V' Oint m = (l+r)/2; // X[l:m] 在A中,余下的在B中" _0 z2 i( H: P: G, ^; {
& u1 W* K$ x; v- D
// 在Z[l:m] 和Z [ m + 1 : r ]中创建按y排序的表* G* G7 v* v, o8 x) ^1 b; F

4 w, A- N8 _+ S/ Sint f = l, // Z[l:m]的游标
+ k/ s1 s% p0 a9 [8 C2 \# I' P4 |  g$ t# i" t9 ~& A8 B
g = m+1; // Z[m+1:r]的游标
6 Y- y& `1 q+ o/ m7 b
) n; y! J) R  g9 F' y1 X  S1 ufor (int i = l; i &lt;= r; i++)
7 R8 }# m2 B' D5 o# K8 ~
! o# O3 n# ~% g1 wif (Y.p &gt; m) Z[g++] = Y;0 b) p6 l# X# O2 a* j% |
( c6 ~7 [, f7 G. ?) n
else Z[f++] = Y;
6 Q8 e" o2 [4 U$ {. v# _
( J. K& r1 ~& S6 R+ a1 [// 对以上两个部分进行求解* Y# ?( P4 C0 Y

; a: [- C8 v. dc l o s e ( X , Z , Y, l , m , a , b , d ) ;4 B; U7 X2 g1 ^
( B4 `8 D+ i6 y! I, S% D, b: l" G
float dr;/ j/ W, d  Z2 E: N' m9 N

: P, f& Z: h9 u. `6 \6 LPoint1 ar, br;! e# F6 d4 N2 Q- f' `+ k2 h

4 V3 O8 T) M8 z  a. Sc l o s e ( X , Z , Y, m + 1 , r, a r, b r, d r ) ;
: q9 Q8 ~8 G8 F4 Y
6 m9 J8 G8 V/ g// (a,b) 是两者中较近的点对' d3 c% S( M6 r0 r% N1 f6 [3 d

) Z2 F1 |0 W" @* u" Wif (dr &lt; d) {a = ar;
0 h. F5 Y3 }1 z( B1 k
. I- P; b8 i: e5 ]1 |7 A6 z+ e# x7 Bb = br;
+ a5 g! c# r! w' l8 s+ T5 M
0 e' D, \) d5 H* b8 bd = dr;}
' F4 X. x) |0 y5 A# T+ k% E+ K3 ?/ u' y/ i- Z/ [6 |/ q- [) X& L
M e r g e ( Z , Y,l,m,r);// 重构Y
& b: L: R( H# s* `3 e* q
$ X* n& I5 v  o( D. d) W/ /距离小于d的点放入Z
* k( n& C& f* k$ f" B8 A/ |
" s6 I- ]* F7 Mint k = l; // Z的游标4 p/ R  I2 _! l& a

0 \6 f6 T& z; s. b; e; sfor (i = l; i &lt;= r; i++)
5 W+ I9 z& Y. s$ K% V
) h- i7 B' p& _0 n* f; ~if (fabs(Y[m].x - Y.x) &lt; d) Z[k++] = Y;9 f0 n  p+ R  D- h1 ~  \
$ M; i7 G- w2 [4 V, {# l6 n
// 通过检查Z [ l : k - 1 ]中的所有点对,寻找较近的点对7 z( B) H7 Z* Q* ^

# C9 z$ B5 d( X5 q% q- wfor (i = l; i &lt; k; i++){
" d) o0 o) X5 B" l
+ u; V/ `& V0 z+ M( ]0 zfor (int j = i+1; j &lt; k &amp;&amp; Z[j].y - Z.y &lt; d;
/ Q' ~4 c( L0 E9 C; }9 T+ n
' O  w' W$ E4 X+ Sj + + ) {: @# C/ q7 x) N6 |
4 |; p7 _/ G. W9 i1 t
float dp = dist(Z, Z[j]);) M1 m( }" F2 @! v7 Y9 `+ w
- `/ u# {, N' m% c
if (dp &lt; d) {// 较近的点对
4 D) E6 I( g% ^3 _8 r/ I, v7 ~; X& Z$ C0 ?% M" e8 k
d = dp;9 y: i& n/ `  }

  W/ F7 W7 E" B- _a = X[Z.p];( j0 k3 p# X, E! ?$ d

" U+ j! Z3 e2 b# e( H4 r' e) Yb = X[Z[j].p];}' `" R) t# ^- m$ L

' ?( X2 K5 I/ Q: q6 o}1 e' j  O. `3 j, T! b
/ }, L& g: S6 v' s/ i5 ?% H
}
! k( D0 H+ U0 l9 P; S: a4 @. c3 @: C7 t5 T7 F  b4 p8 [3 w, K$ Q% g
}
2 y8 H# @0 ]2 V+ w; s8 D2 K
+ |" c, B, {( l/ Z5 Q+ ?4 Z% ?/ {函数c l o s e(见程序1 4 - 11)用来确定X[1:r] 中的最近点对。假定这些点按x 坐标排序。在Y [ 1 : r ]中对这些点按y 坐标排序。Z[ 1 : r ]用来存放中间结果。找到最近点对以后,将在a, b中返回最近点对,在d 中返回距离,数组Y被恢复为输入状态。函数并未修改数组X。7 o# a! Q+ j' ~9 y. c

, y2 [7 i7 j% i/ }) L; S2 @5 Q2 S  j首先考察“小问题”,即少于四个点的点集。因为分割过程不会产生少于两点的数组,因此只需要处理两点和三点的情形。对于这两种情形,可以尝试所有的可能性。当点数超过三个时,通过计算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 ]。
% y: U0 n! W" s6 R# s; C! I& G5 f1 X
为实现图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
+ t, j8 |- e3 `/ t/ I
/ r( w0 W6 B" f1 b  p5 h( i还是在RB中)与Z[j] 配对来实现,其中i<j 且Z [ j ] . y - Z [ i ] . y< 。对每一个Z [ i ],在2 × 区域内所检查的点如图1 4 - 1 7所示。由于在每个2 × 子区域内的点至少相距。因此每一个子区域中的点数不会超过四个,所以与Z [ i ]配对的点Z [ j ]最多有七个。
0 B/ z$ y# \" s5 W7 J" [8 M/ w. \( Q/ j
2. 复杂性分析4 U5 U5 J# \8 `6 i- p3 D5 [( W+ B8 o7 a( Y

' a1 f% s8 ]6 v* V" j  G令t (n) 代表处理n 个点时,函数close 所需要的时间。当n<4时,t (n) 等于某个常数d。当n≥4时,需花费(n) 时间来完成以下工作:将点集划分为两个部分,两次递归调用后重构Y,淘汰距分割线很远的点,寻找更好的第三类点对。两次递归调用需分别耗时t (「n /2ù」和t (?n /2?).
8 y9 O6 b  b  c2 G; j3 a1 b, K) ?2 R* z/ k- x8 U
这个递归式与归并排序的递归式完全一样,其结果为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-6-12 13:37 , Processed in 0.404012 second(s), 51 queries .

回顶部