`

平面最近点对

 
阅读更多

求点集中的最近点对有以下两种方法:

设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

1、蛮力法(适用于点的数目比较小的情况下)

1)算法描述:已知集合S中有n个点,一共可以组成n(n-1)/2对点对,蛮力法就是对这n(n-1)/2对点对逐对进行距离计算,通过循环求得点集中的最近点对:

2)代码描述:

double MinDistance = double.maxvalue; //设置一个MinDistance存储最近点对的距离,初始值为无穷大

int PointIndex1,PointIndex2; //设置PointIndex1,PointIndex2分别存储最近点对的两个点编号

for (i=1; i< n; i++) //循环计算n(n-1)/2对点对的距离
{

for (j=i+1; j<=n; j++)
{

double PointDistance = Distance(S[i],S[j]); //求得point i和point j之间的距离

if PointDistance < MinDistance; //如果当前点对距离小于最小点对距离,则设置最小点对距离等于当前点对距离

{

MinDistance = PointDistance;

PointIndex1 = i;

PointIndex2 = j;

}

}

}

}
3)算法时间复杂度:算法一共要执行 n(n-1)/2次循环,因此算法复杂度为O(n2)

2、分治法

1)算法描述:已知集合S中有n个点,分治法的思想就是将S进行拆分,分为2部分求最近点对。算法每次选择一条垂线L,将S拆分左右两部分为SL和SR,L一般取点集S中所有点的中间点的x坐标来划分,这样可以保证SL和SR中的点数目各为n/2

(否则以其他方式划分S,有可能导致SL和SR中点数目一个为1,一个为n-1,不利于算法效率,要尽量保持树的平衡性)

依次找出这两部分中的最小点对距离:δL和δR,记SL和SR中最小点对距离δ = min(δL,δR),如图1:

以L为中心,δ为半径划分一个长带,最小点对还有可能存在于SL和SR的交界处如下图2左图中的虚线带,p点和q点分别位于SL和SR的虚线范围内,在这个范围内,p点和q点之间的距离才会小于δ,最小点对计算才有意义。



Figure 2

对于SL虚框范围内的p点,在SR虚框中与p点距离小于δ的顶多只有六个点,就是图二右图中的2个正方形的6的顶点。这个可以反推证明,如果右边这2个正方形内有7个点与p点距离小于δ,例如q点,则q点与下面正方形的四个顶点距离小于δ,则和δSLSR的最小点对距离相矛盾。因此对于SL虚框中的p点,不需求出p点和右边虚线框内所有点距离,只需计算SR中与p点y坐标距离最近的6个点,就可以求出最近点对,节省了比较次数。

(否则的话,最坏情形下,SR虚框中有可能会有n/2个点,对于SL虚框中的p点每次要比较n/2次,浪费了算法的效率

代码描述:

1)对点集S的点x坐标和y坐标进行升序排序,获得点集Sx和Sy

2)令δ=∞; //δ为最小点位距离

3)Divide_conquer(Sx,Syδ//分治法

if (Sx.count=1) then δ=∞; //如果Sx中只有一个点,则δ=

return δ;

else if(Sx.count=2 and d(Sx.[0],Sx.[1])<δ//如果Sx中只有2个点,则δ为两点之间距离

δ=d(Sx.[0],)Sx.[1]);

return δ;

else //如果Sx中多于2个点,则Sx,Sy分治,以中心点画线,将Sx分为左右两部分SxL和SxR,Sy分为SyLSyR

j1=1,j2=1,k1=1,k2=1;

mid = Sx.count/2; //midSx中的中间点点号

L = Sx.[mid].x; //LSx中的中间点x坐标

for(i=1,i<Sx.count,i++)

{

if(i<=mid) //将Sx中间线以左地方的点存入到SxL,新数组保持原来的升序性质

SxL[k1] = Sx[i] k1++;

else //将Sx中间线以右的地方的点存入到SxR数组保持原来的升序性质

SxR.count[k2] = Sx[i] k2++;

if(Sy[i].x <L) //将Sy中间线以左地方的点存入到SyL数组保持原来的升序性质

SyL[j1] = Sx[i] j1++;

else //将Sy中间线以右地方的点存入到SyR数组保持原来的升序性质

SyR[j2] = Sx[i] j2++;

}

δL = Divide_conquer(SxL,SyLδ); //获取Sx中的的最小点位距离δL

δR = Divide_conquer(SxR,SyRδ); //获取Sy中的的最小点位距离δR

δ= min (δL,δR);

δ=merge(SyL,SyRδ); //获SxSy交界处的最小点位距离,并综合δLδR 求出点集的最小点位距离δ

return δ;

函数merge(SyL,SyRδ)

merge(SyL,SyRδ)

{

i1=1,i2=1;

for(i=1,i<SyL.count,i++) //获取SyL中在左边虚框(距离小于δ)内的点,存入到S'yL数组保持原来的升序性质

{

if(SyL[i].x>L-δ)

then S'yL[i1]= SyL[i], i1++,

}

for(i=1,i<SyR.count,i++) //获取SyR中在右边虚框(距离小于δ)内的点,存入到S'yR数组保持原来的升序性质

{

if(SyR[i].x<L+δ)

then S'yR[i2]= SyR[i], i2++,

}

t=1;

for(i=1,i<S'yL.count,i++)

{

while(S'yR[t].y< S'yL[t].yand t < SyR.count) //获取点集S'yR内距离点S'yL[t]y坐标最接近的点号

{ t++; }

for( j= max(1,t-3), j<=min(t+3,S'yR.count),j++) //计算S'yR中的点与S'yL[t]y坐标相邻的六个点的距离

{

if(d(S'yL[i],S'yL[j])<δ) //如果前两点之间距离小于δ

then δ = d(S'yL[i],S'yL[j]); //则最小点位距离δ为当前两点之间距离

}

return δ

}

3)算法时间复杂度:

首先对点集S的点x坐标和y坐标进行升序排序,需要循环2nlogn次,复杂度为O(2nlogn)

接下来在分治过程中,对于每个S'yL中的点,都需要与S'yR中的6个点进行比较

O(n)= 2O(n/2) + (n/2)*6(一个点集划分为左右两个点集,时间复杂度为左右两个点集加上中间区域运算之和)

其解为O(n)< O(3nlogn)

因此总的时间复杂度为O(3nlogn),比蛮力法的O(n2)要高效。

分治法基础知识可参考http://blog.csdn.net/junerfsoft/archive/2008/09/25/2975495.aspx

改进算法可参考“求平面点集最近点对的一个改进算法”


分享到:
评论

相关推荐

    平面最近点对问题分治算法解答,C++实现

    平面最近点对问题分治算法解答,C++实现,代码整洁规范。

    平面最近点对_somewhere1dd_平面最近点对_最近点对_平面最接近点对_平面点_

    这个题目所提及的“平面最近点对_somewhere1dd_平面最近点对_最近点对_平面最接近点对_平面点_”显然是对这个问题的描述,而提供的“平面最近点对.c”文件则可能包含了用C语言实现的解决方案。 平面最近点对问题的...

    平面最近点对1.zip

    "平面最近点对"问题是一个典型的分治算法应用实例,它涉及到二维空间中点集的处理,目标是找出距离最近的两个点。 首先,我们要理解什么是平面最近点对。在二维平面上,如果有n个点,我们需要找到其中任意两点之间...

    ConsoleApplication17_分治策略求平面最近点对_

    《平面最近点对的分治策略求解》 在计算机科学和算法设计中,分治策略是一种解决问题的有效方法,尤其适用于处理复杂度较高的问题。在本篇中,我们将深入探讨如何利用分治策略来求解平面内的最近点对问题。这个问题...

    closest_pair_of_points.zip_closest points pair_平面最近点对_最近点对_计算几何

    标题“closest_pair_of_points.zip_closest points pair_平面最近点对_最近点对_计算几何”指的是一个关于解决平面最近点对问题的C++11实现。在这个压缩包中,开发者提供了一种解决方案,包括了基本的暴力搜索方法...

    Computational-Geometry.rar_geometry_point in polygon_平面最近点对

    最后,"平面最近点对"问题是在给定一组点集的情况下,寻找其中距离最近的点对。解决这个问题通常可以采用分治策略,如划分平面为四分区域并递归查找,或者使用kd树、球树等空间索引结构。算法的基本思想是将问题分解...

    数据结构课程设计:用分治法算法解平面最近点对问题

    本资源为文档类型,内有相关代码,题目是用分治法解平面最近点对问题,希望有帮助!

    分治法求平面最近点报告

    ### 分治法求平面最近点知识点详解 #### 实验目的 本实验旨在通过具体实践,帮助学生深入理解分治法的基本原理及其应用。通过实验,学生需掌握以下几点: 1. **问题描述**:理解平面最近点问题的具体背景与意义。 2...

    分治法求最近点对问题

    1. **最近点对问题**:给定平面上的N个点,找到其中两点间的最小距离。 2. **随机点集生成与算法实现**:生成不同数量的随机点集,并采用蛮力法和分治法计算这些点集的最近点对。 3. **算法效率比较**:分别统计两种...

    分治法求最近点对代码

    1. 对于平面上给定的N个点,给出所有点对的最短距离,即,输入是平面上的N个点,输出是N点中具有最短距离的两点。 2. 要求随机生成N个点的平面坐标,应用蛮力法编程计算出所有点对的最短距离。 3. 要求随机生成N个点...

    java实现分治法寻找最近点对

    使用java编写 用分治法实现对于平面上最近点对的查找 使用Swing作为界面

    最近点对+Fibonacci两个分治

    在每一步,他们会计算当前子集中的最近点对,并与之前子集的最近点对进行比较,以确定全局的最近点对。 实验报告可能包含了以下内容:问题定义、算法描述、时间复杂度分析、代码实现细节、测试案例及结果验证。学生...

    分治法平面最接近点对C++实现

    在平面最接近点对(Closest Pair of Points)问题中,我们给定一组在二维平面上的点,目标是找到距离最近的两个点。这是一个典型的分治法应用实例,尤其是在点的数量非常大时,直接遍历所有点对会非常耗时。C++作为...

    平面上n个点之间最近点对问题

    在计算机科学领域,解决平面上n个点之间最近点对问题是一个经典的算法问题。这个问题的目标是找到一组给定点中距离最近的两个点。这在地理信息系统、数据挖掘和图形学等领域有着广泛的应用。本问题可以通过多种算法...

    带界面的平面上寻找最近点对

    标题中的“带界面的平面上寻找最近点对”是一个经典的计算机科学问题,通常在图形学、数据结构和算法领域出现。这个问题旨在在一个二维平面上找到距离最近的两个点,而这里的“带界面”指的是该算法被实现为一个具有...

    最近点对问题.cpp

    简洁明了,易于理解,非常好好好好好好,最近点对问题,随机生成1-10之间的浮点数,完美解决随机浮点数的问题

    平面上寻找最近点对的C算法实现

    其中,寻找平面上最近点对问题是该领域内一道经典且基础的题目,它的解决对于地理信息系统、图像处理、机器学习等多个领域都有着广泛的应用。本文将探讨如何在C语言中实现寻找最近点对的算法,以及该实现所面对的...

    求平面点集最近点对的一个改进算法

    求平面点集最近点对的一个改进算法,求平面点集最近点对的一个改进算法

    用分治法结局最近对问题(输出两点坐标及其距离)

    - **合并:** 比较左右两边最近点对的距离,选择距离更小的一组作为全局最近点对。 **3. 跨域中间线的点对检查** 对于跨越中间线的点对,需要特别注意,因为可能存在距离比左右两部分内部的最近点对更近的情况。这...

    用分治算法解平面最接近点对问题

    【平面最接近点对问题】是指在平面上给定n个点,寻找其中距离最近的两点。这是一个经典的计算几何问题,对于大规模数据处理时,直接的暴力求解方法(检查所有点对)效率低下。 **分治算法**是解决此类问题的一种...

Global site tag (gtag.js) - Google Analytics