- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
最近点对问题-Read
最近点对问题
I.一维问题:
一、问题描述和分析
最近点对问题的提法是:给定平面上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小。
严格的讲,最接近点对可能多于1对,为简单起见,只找其中的1对作为问题的解。简单的说,只要将每一点与其它n-1个点的距离算出,找出达到最小距离的2点即可。但这样效率太低,故想到分治法来解决这个问题。也就是说,将所给的平面上n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点。然后在每个子集中递归的求其最接近的点对。这里,关键问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决,但如果这2个点分别在S1和S2中,问题就不那么简单了。下面的基本算法中,将对其作具体分析。
二、基本算法
假设用x轴上某个点m将S划分为2个集合S1和S2,使得S1={x∈S|x=m};S2={x∈S|xm}。因此,对于所有p∈S1和q∈S2有pq。
递归的在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设d=min{|p1-p2|,|q1-q2|}。由此易知,S中的最接近点对或者是{p1,p2},或者是{q1,q2},或者是某个{p3,q3},其中p3∈S1且q3∈S2。如下图所示:
注意到,如果S的最接近点对是{p3,q3},即|p3-q3|d,则p3和q3两者与m的距离不超过d,即|p3-m|d,|q3-m|d。也就是说,p3∈(m-d,m],q3∈(m,m+d]。由于每个长度为d的半闭区间至多包含S1中的一个点,并且m是S1和S2的分割点,因此(m-d,m]中至少包含一个S中的点。同理,(m,m+d]中也至少包含一个S中的点。由上图知,若(m-d,m]中有S的点,则此点就是S1中最大点。同理,若(m,m+d]中有S的点,则此点就是S2中最小点。因此,用线性时间就可以找到区间(m-d,m]和(m,m+d]中所有点,即p3和q3。从而用线性时间就可以将S1的解和S2的解合并成为S的解。其中,为使S1和S2中有个数大致相等的点,选取S中个点坐标的中位数来作分割点m。具体算法实现见程序。
三、实现环境
本程序在VC++环境下实现。
四、测试情况
本程序可按屏幕提示进行输入操作,即相应输出如下:
输入一维点集的各元素(以-1结束):
5 3 9 6 8 15 26 -1
该一维点集中最近点对为(9,8),其距离为1
五、源代码
#include iostream.h
#define M 20
struct cpair//表示具有最近距离的点对(d1,d2)的距离dist
{
float dist;
float d1,d2;
};
int input(float s[],int n)//s[]为一维点集,n为s[]中的元素个数
{
cout输入一维点集的各元素(以-1结束):\n;
n=0;
cins[n];
while(s[n]!=-1)
{
n++;
cins[n];
}
return n;
}
float max(float s[],int b,int e)//返回s[b]到s[e]中的最大值
{
float m1=s[b];
for(int i=b+1;i=e;i++) if(m1s[i]) m1=s[i];
return m1;
}
float min(float s[],int b,int e)//返回s[b]到s[e]中的最小值
{
float m1=s[b];
for(int i=b+1;i=e;i++) if(m1s[i]) m1=s[i];
return m1;
}
//返回s[]中的具有最近距离的点对及其距离
cpair cpair1(float s[],int n)
{
cpair temp={1000,0,0};
//当点集中元素的个数不足2时,返回具有无穷大的dist值(此处设为1000)的temp
if(n2) return temp;
float m1=max(s,0,n-1),m2=min(s,0,n-1);
float m=(m1+m2)/2;//找出点集中的中位数
int j=0,k=0;
//将点集中的各元素按与m的大小关系分组
float s1[M],s2[M];
for(int i=0;in;i++)
{
if(s[i]=m) {s1[j]=s[i];j++;}
else {s2[k]=s[i];k++;}
}
cpair d1=cpair1(s1,j),d2=cpair1(s2,k);//递归
float p=max(s1,0,j-1),q=max(s
文档评论(0)