求最近点对

 求最近点对 就我所知道的 有三种算法,一是算法导论上给出的,用分治思想,时间复杂度为O(n log(n)),详细可见算法导论

第二种是网上给出的 随机算法  时间复杂度为O(n ),

原文如下:

对于给定的平面上的n个点(xi,yi)( i=1,2,…,n)和一个距离d,

以d为尺寸可以构造一个(逻辑上的)网格,

该网格以(min{xi},min{yj})为网格的最左下点,

之后以步长d不断向右、向上伸展为长方形网格;

使得(max{xi},max{yj})也含在其中。

由于所有的点均在长方形网格中,最近点对也必在其中。

对每个尺寸为d×d的方格,分别向左向上、向右向上、向左向下、

向右向下各扩展一格,可得4个2d×2d的方格 (i=1,2,3,4)。

定理:设已知平面上的某两点的距离为d。

若最近点对中的一个点落在某个d×d方格 中,

则在上述的4个2d× 2d方格 (i=1,2,3,4)中,

至少有一个同时含有最近点对的两个点。

推论:若已知平面上的某两点的距离为d,

  且算法对长方形网格中每一个2d×2d方格中的所有点对,

均一一计算其距离,则该算法一定可以找出最近点对。

算法:

在点集S(|S|=n)中随机地取一个子集T,使得|T|= ë û。

   (按随机取样算法的分析,n个中取m个(m≤n)时间为O(n))

对T中的所有点对逐一计算距离,求出最近点对距离d(T)。

   (点对数为ë û( ë û-1)/2,每个点对计算时间为O(1),

     故总的计算时间为O(ë û2)= O(n)。)

以d(T)为尺寸构造一个(逻辑上的)长方形网格,

(设长方形的横向共有m格,纵向共有r格。)

如果m*r≤cn(c可取2~10,取何值合适见后面的讨论),

则开设一个m×r的指针矩阵P、和一个m×r的计数矩阵Q,

然后逐一扫描S中的点sk:

如果sk落在方格 中(i,j分别表示所在方格横向、纵向位置),

则把该点放入P[i,j]所指的链表内,Q[i,j]增1,

直至n个点全部检查为止。

(每个点计算时间为O(1),故总的计算时间为O(n)。)

然后扫描Q数组,找到含顶点最多的方格 。(时间为O(n))

如果 中点数≤ ,则逐一计算 中的点距离(时间为O(n)),

求出其中的最近点对及新的d’(如果d’比d小的话)。

如果 中点数> ,则把 一分为4,成为4个 × 的方格,

找出其中含点最多的方格,一直拆分到方格中的点数≤ ,

求出其中的最近点对及新的d’(时间复杂度期望值是O(n))。

若m*r>cn,则在素数表中找一个略小于cn的素数p,

然后逐一检查S中的点sk,找到其所在方格 (时间为O(n)),

用散列函数H(i,j,p)把sk散列至长为p的桶中:

桶中的每个槽只对应一个方格 (若发生冲突,用冲突处理机制),

每个槽要记录方格中点的个数,各个点用链表连接起来。

S的检查完成以后,找到含点数最多的 方格(时间为O(n)),

用前述方法计算出该方格中的最近点对和新d’(如果d’比d小的话)。

以新d’为尺寸构造一个(逻辑上的)新网格,

设网格中的小方格数为m’×r’,则在这个网格中

恰有(m’-1)×(r’-1)个尺寸为2d’×2d’的方格。

由定理知,最近点对必定落在某个 之中。

逐一检查S中的点,依次把这些点放入(m’-1)×(r’-1)个指针

所指的链表中(或长度为p的散列表中)。(时间复杂度是O(n))

6) 逐一检查含有2个点以上的方格 ,

对方格中的所有点对进行计算,与当前最小的d*比较,

若小于d*,则更新d*、更新当前的最近点对。

当所有含2个点以上的2d×2d方格检查完毕时,

点集中的最近点对也就找到了。根据概率分析,

此项工作的时间复杂度期望值是O(n)。

关于c的取值(c可取2~10):

c取值大的好处是需要散列的可能性降低,可直接处理二维表,

且每一个格子中的顶点数相对要少,第6步中工作量减少;

坏处是循环次数增多。c取的小的好处、坏处则反之。

一般来说,若顶点较密集,则c要取的稍大。

(说来惭愧,我刚开始没看懂,晓文看懂后给我讲的,感谢他)

第三种是老杨上课讲的,时间复杂度也为O(n log(n)), 感觉借鉴了上诉两种思想,和第一种的划分方式有所不同,算法导论上是用垂线划分,老杨用面积划分,一次划分一半找到含点数最多的面积,在进行划分,直到省两个点,找到最近距离,然后按照 上诉第二种中的方法以此距离做网格,以点的横纵坐标分别排序,找相邻两点的最短距离(在中距离是用了技巧,当横坐标或是纵坐标的差的绝对值大于前面找的距离时,不进行比较,直接排除)。最后找到的最短距离即是所求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值