实验项目
设p1=(x1,y1),p2=(x2,y2),…,pn=(xn,yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。
实验目的
(1) 进一步掌握递归算法的设计思想以及递归程序的调试技术;
(2) 理解这样一个观点:分治与递归经常同时应用在算法设计之中。
实验要求
(1) 分别用蛮力法和分治法求解最近对问题;
(2) 分析算法的时间性能,设计实验程序验证分析结论。
算法设计与实现
1.蛮力法
(1)基本思想
蛮力法求解最近对问题的过程是:分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计算两次距离,只考虑
i<j
i
<
j
的那些点对(Pi,Pj)。
(2)算法设计
struct Point
{
double x;
double y;
};
double ClosePoints(int n,Point a[],int &index1,int &index2)
{
double d;
double Dist=10000;
for (int i=0;i<n-1;i++)
{
for (int j=i+1;j<=n-1;j++)
{
d=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
if(d<=Dist)
{
Dist=d;
index1=i;
index2=j;
}
}
}
return Dist;
}
(3)复杂度分析
算法的基本操作是计算两个点的欧几里得距离。注意到在求欧几里得距离时,避免了求平方根操作,其原因是:如果被开方的数越小,则它的平方根也越小。所以,算法的基本操作就是求平方,其执行次数为:
2.分治法
(1)基本思想
我们用分治法解决最近对问题,就是将集合S分成两个子集S1和S2,每个子集中有n/2个点。然后在每个子集中递归的求其最接近的点对,在求出每个子集的最接近点对后,关键问题是如何实现分治法中的合并步骤,如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。但是,如果这2个点分别在S1和S2中,则对于S1中任一点p,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需计算才能得到准确结果。
(2)算法设计
double DivPoints(point p[],int begin,int end)
{
int i,j;
int n=end-begin+1;
int m=(begin+end)/2;
if(n==2)
return Distence(p[begin],p[end]);//返回两个点距离
if(n==3)//三个点直接求最近点并返回距离
{
double d1 = Distence(p[begin], p[begin+1]);
double d2 = Distence(p[begin+1], p[end]);
double d3 = Distence(p[begin], p[end]);
if(d1<=d2 && d1<=d3)
return d1;
else if (d2 <= d3)
return d2;
else
return d3;
}
double left=DivPoints(p,begin,m);
double right=DivPoints(p,m+1,end);
double d=min(left,right);
int k,l,flag=0;
//找到以m为中心的与m横坐标距离小于sqrt(d)的点
for(i=begin;i<=end;i++)
{
if(flag==0 && (p[m].x-p[i].x)<=sqrt(d))
{
flag=1;
k=i;
}
if((p[i].x-p[m].x) <= sqrt(d))
l=i;
}
for (i=k;i<=m;i++)
{
for (j=m+1;j<=l && fabs((p[j].y-p[i].y))<sqrt(d);j++)
{
if(Distence(p[i],p[j]) <= d)
d=Distence(p[i],p[j]);
}
}
return d;
}
(3)复杂度分析
应用分治法求解含有n个点得最近对问题,其时间复杂性可由下面的递推式表示:
实验结果与分析
随机生成一定数量的点,分别用蛮力法和分治法求解最近对问题,统计算法运行的时间。
(1)实验结果
点的个数 | 蛮力法求解时间 | 分治法求解时间 |
---|---|---|
50 | 3.36422e-005s | 8.86672e-005s |
100 | 0.000122309s | 0.000157377s |
500 | 0.0029819s | 0.00102267s |
1000 | 0.0124858s | 0.00237634s |
5000 | 0.289743s | 0.0132567s |
(2)实验分析
从实验结果可以看出,在点数规模较小时,蛮力法效率较高,当点数规模较大后,分治法效率明显比蛮力法要高。