中科大算法实验4求平面最近点对算法Word格式文档下载.docx

上传人:b****6 文档编号:19344933 上传时间:2023-01-05 格式:DOCX 页数:13 大小:533.69KB
下载 相关 举报
中科大算法实验4求平面最近点对算法Word格式文档下载.docx_第1页
第1页 / 共13页
中科大算法实验4求平面最近点对算法Word格式文档下载.docx_第2页
第2页 / 共13页
中科大算法实验4求平面最近点对算法Word格式文档下载.docx_第3页
第3页 / 共13页
中科大算法实验4求平面最近点对算法Word格式文档下载.docx_第4页
第4页 / 共13页
中科大算法实验4求平面最近点对算法Word格式文档下载.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

中科大算法实验4求平面最近点对算法Word格式文档下载.docx

《中科大算法实验4求平面最近点对算法Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《中科大算法实验4求平面最近点对算法Word格式文档下载.docx(13页珍藏版)》请在冰豆网上搜索。

中科大算法实验4求平面最近点对算法Word格式文档下载.docx

如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。

但是,如果这2个点分别在S1和S2中,则对于S1中任一点p,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需做n2/4次计算和比较才能确定S的最接近点对。

因此,依此思路,合并步骤耗时为O(n2)。

整个算法所需计算时间T(n)应满足:

 T(n)=2T(n/2)+O(n2)

在一维的情形,距分割点距离为δ的2个区间(m-δ,m](m,m+δ]中最多各有S中一个点。

因而这2点成为唯一的末检查过的最接近点对候选者。

二维的情形则要复杂些,此时,P1中所有点与P2中所有点构成的点对均为最接近点对的候选者。

在最坏情况下有n2/4对这样的候选者。

但是P1和P2中的点具有以下的稀疏性质,它使我们不必检查所有这n2/4对候选者。

考虑P1中任意一点p,它若与P2中的点q构成最接近点对的候选者,则必有d(p,q)<

δ。

满足这个条件的P2中的点有多少个呢?

容易看出这样的点一定落在一个δ×

2δ的矩形R中.

因此d(u,v)≤5δ/6<

δ。

这与δ的意义相矛盾。

也就是说矩形R中最多只有6个S中的点。

图4(b)是矩形R中含有S中的6个点的极端情形。

由于这种稀疏性质,对于P1中任一点p,P2中最多只有6个点与它构成最接近点对的候选者。

因此,在分治法的合并步骤中,我们最多只需要检查6×

n/2=3n对候选者,而不是n2/4对候选者。

这是否就意味着我们可以在O(n)时间内完成分治法的合并步骤呢?

现在还不能作出这个结论,因为我们只知道对于P1中每个S1中的点p最多只需要检查P2中的6个点(确切的说,是矩形R中的6个S中的点),但是我们并不确切地知道要如何检查。

为了解决这个问题,我们可以将p和P2中所有S2的点投影到垂直线l上。

由于能与p点一起构成最接近点对候选者的S2中点一定在矩形R中,并且要满足d(p,q)<

δq∈P2,因此满足条件的点它们在直线l上的投影点距p在l上投影点的距离小于δ,由上面的分析可知,这种投影点不多于6个。

因此,若将P1和P2中所有S的点按其y坐标排好序,则对P1中所有点p,对排好序的点列作一次扫描,就可以找出所有最接近点对的候选者,对P1中每一点最多只要检查P2中排好序的相继6个点。

至此,我们可以给出用分治法求二维最接近点对的算法CPAIR2如下:

functionCPAIR2(S);

begin

if|S|=2

thenδ:

=S中这2点的距离

elseif|S|=0

=∞

else

1.m:

=S中各点x坐标值的中位数;

构造S1和S2,使S1={p∈S|px≤m}和S2={p∈S|px>

m}

2.δ1:

=CPAIR2(S1);

δ2:

=CPAIR2(S2);

3.δm:

=min(δ1,δ2);

4.设P1是S1中距垂直分割线l的距离在δm之内的所有点组成的集合,P2是S2中距分割线l的距离在δm之内所有点组成的集合。

将P1和P2中的点依其y坐标值从小到大排序,并设P1*和P2*是相应的已排好序的点列;

5.通过扫描P1*以及对于P1*中每个点检查P2*中与其距离在δm之内的所有点(最多6个)可以完成合并。

当P1*中的扫描指针逐次向上移动时,P2*中的扫描指针可在宽为2δm的一个区间内移动。

设δl是按这种扫描方式找到的点对间的最小距离;

6.δ=min(δm,δl);

end;

return(δ);

下面我们来分析一下算法CPAIR2的计算复杂性。

设对于n个点的平面点集S,算法耗时T(n)。

算法的第1步和第5步用了O(n)时间,第3步和第6步用了常数时间,第2步用了2T(n/2)时间。

若在每次执行第4步时进行排序,则在最坏情况下第4步要用O(nlogn)时间。

这不符合我们的要求。

因此,在这里我们要作一个技术上的处理。

我们采用设计算法时常用的预排序技术,即在使用分治法之前,预先将S中n个点依其y坐标值排好序,设排好序的点列为P*。

在执行分治法的第4步时,只要对P*作一次线性扫描,即可抽取出我们所需要的排好序的点列P1*和P2*。

然后,在第5步中再对P1*作一次线性扫描,即可求得δl。

因此,第4步和第5步的两遍扫描合在一起只要用O(n)时间。

这样一来,经过预排序处理后的算法CPAIR2所需的计算时间T(n)满足递归方程:

显而易见T(n)=O(nlogn),预排序所需的计算时间为O(n1ogn)。

因此,整个算法所需的计算时间为O(nlogn)。

在渐近的意义下,此算法已是最优的了。

二、核心代码:

1.生成随机数:

如图,使用C#代码,先生成坐标的随机数:

2.生成的随机数之后,将这些点以中位数分治:

Closetpair是递归函数。

3.求中位数的最进点对,将这些点对放到新的数组中:

4.将这些最近点对按y坐标排序:

由于C#库函数只能对数组排序,不得不将对象数组取出来,拍完序之后再放回去:

5.每个点与附近7个点进行比较:

 

三、结果与分析:

1.输出15,随机生成15个坐标对:

2.输入155,随机生成坐标对:

随机生成15万个:

分析:

如果在递归调用时,不对Y排序,非常卡,运行15万个坐标至少要运行5分钟。

所以,主函数要对X排序,递归时要对Y排序。

四、备注

总结:

本实验重点:

(1)主函数对X排序,递归时对Y排序。

(2)筛选的中位数附近的点,对每个点取六个比较即可。

(3)如图:

附录(源代码)

算法源代码(C/C++/JAVA描述)C#:

publicpartialclassForm1:

Form

{

publicForm1()

InitializeComponent();

}

publicclassPoint

publicfloatx,y;

publicstaticfloatNo_distance=1000000;

publicstaticfloatAAA,BBB,CCC,DDD;

publicstaticvoidSetPoints(Point[]points,intlength)

Randomra=newRandom();

for(inti=0;

i<

length;

i++)

points[i]=newPoint();

points[i].x=(float)ra.NextDouble()*200-100;

points[i].y=(float)ra.NextDouble()*200-100;

publicstaticfloatDistance(Pointa,Pointb)

return(float)Math.Sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

publicstaticfloatClosetspair(Point[]points,intlength,Pointa,Pointb)

floatdistance;

//记录集合中最近的两点

floatd1,d2;

//记录分割后两个子集中各自最小点对距离

inti=0,j=0,k=0;

//用于控制for循环的循环变量

Pointa1=newPoint();

Pointb1=newPoint();

Pointa2=newPoint();

Pointb2=newPoint();

//保存分割后两个子集中最小点对

if(length<

2)returnNo_distance;

//如果子集长度小于2,定义为最大距离,表示不可达

if(length==2)

distance=Distance(points[0],points[1]);

else

Point[]pts1=newPoint[length];

//两个子集分别放入这两个

Point[]pts2=newPoint[length];

floatmid=points[(length-1)/2].x;

//排完序后的中间下标值,即中位数

for(i=0;

length/2;

pts1[i]=points[i];

for(j=0,i=length/2;

pts2[j++]=points[i];

d1=Closetspair(pts1,length/2,a1,b1);

d2=Closetspair(pts2,length-length/2,a2,b2);

if(d1<

d2){distance=d1;

a=a1;

b=b1;

else{distance=d2;

a=a2;

b=b2;

//求解跨分割线,并在6*26区间内最近的点对

Point[]pts3=newPoint[length];

for(i=0,k=0;

if(Math.Abs(points[i].x-mid)<

=distance)pts3[k++]=points[i];

float[]array=newfloat[k];

for(intiii=0;

iii<

k;

iii++)

array[iii]=pts3[iii].x;

Array.Sort(array);

for(intia=0;

ia<

ia++)

pts3[ia].x=array[ia];

for(j=i+1;

j<

=i+7&

&

j++)//只需与有序的领接的的7个点进行比较

if(Distance(pts3[i],pts3[j])<

distance)

{//如果跨分割线的两点距离小于已知最小距离,则记录该距离

distance=Distance(pts3[i],pts3[j]);

a=pts3[i];

b=pts3[j];

AAA=a.x;

BBB=a.y;

CCC=b.x;

DDD=b.y;

returndistance;

privatevoidbutton1_Click(objectsender,EventArgse)

intN;

//随机生成的点对个数。

Pointa=newPoint();

Pointb=newPoint();

floatdistence;

if(textBox2.Text=="

"

MessageBox.Show("

请您先输入需要随机生成的多少对?

"

你好!

输入为空"

MessageBoxButtons.OKCancel);

else{

N=Int32.Parse(textBox2.Text.Trim());

if(N<

2)

请输入大于等于2的点个数!

);

Point[]points=newPoint[N];

SetPoints(points,N);

N;

listBox1.Items.Add("

("

+points[i].x+"

+points[i].y+"

)"

float[]array=newfloat[N];

array[iii]=points[iii].x;

points[ia].x=array[ia];

listBox2.Items.Add("

distence=Closetspair(points,N,a,b);

textBox1.Text="

最近点对为:

+"

+AAA+"

+BBB+"

)和"

+CCC+"

+DDD+"

;

textBox3.Text="

最近点对距离为:

+distence;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 临床医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1