当前位置:文档之家› 最接近点对问题实验报告

最接近点对问题实验报告

最接近点对问题
一.实验目的:
1.理解算法设计的基本步骤及各步的主要内容、基本要求;
2.加深对分治设计方法基本思想的理解,并利用其解决现实生活中的问题;
3.通过本次实验初步掌握将算法转化为计算机上机程序的方法。

二.实验内容:
1.编写实现算法:给定n对点,在这n对点中找到距离最短的点对。

2.将输出数据存放到另一个文本文件中,包括结果和具体的运行时间。

3.对实验结果进行分析。

三.实验操作:
1.最接近点对查找的思想:
首先,将所有的点对按照x坐标排序,找到x坐标的中位数,将所有的点对分成三部分,横坐标小于x(S1)、等于x(S2)和大于x(S3)的点对,在求取每部分中的最短距离,利用分治法,一步步地分解为子问题,找到最短距离d。

由于距离最近的两个点可能在不同的区域中,需要进一步判断。

选择S1中的一个点,由于与它相比较的点的距离不可能超过d,故其配对范围为d*2d的矩形,将这个矩形划分为6份2/d*3/d的小矩形,其对角线的长度为5/6d,小于d,故S1中的任意一个点只需和S2中的6个点比较即可,最终确定最短的距离。

2.取中位数:
为了减少算法的时间开销,需要将所有的点对进行分组,以中位数为基准,考虑到快速排序的不稳定性,本次排序使用了合并排序。

代码实现:
template <class Type>
void Merge(Type c[],Type d[],int l,int m,int r){
int i = l,j = m + 1,k = l;
while((i<=m)&&(j<=r)){
if(c[i]<=c[j]) d[k++] = c[i++];
else d[k++] = c[j++];
}
if(i>m) {
for(int q=j; q<=r; q++) d[k++] = c[q];
}
else{
for(int q=i; q<=m; q++) d[k++] = c[q];
}
}
template <class Type>
void MergeSort(Type a[],Type b[],int left,int right){
if(left<right){
int i = (left + right)/2;
MergeSort(a,b,left,i);
MergeSort(a,b,i+1,right);
Merge(a,b,left,i,right);//合并到数组a
Copy(a,b,left,right);//复制回数组a
}
}
3.数据存入文件:
本次对文件的输入没有存入文本文件中,只将输出数据输入到指定的文件夹中,用到了输出流文件。

代码实现:
ofstream outFile;
outFile.open("E://程序设计/practice 1/算法设计与分析/文本文
件夹/最接近点对问题结果.txt",ios::trunc);
int length;
cout<<"请输入点对数:";
cin>>length;
xPosition X[M];
cout<<"随机生成的二维点对为:"<<endl;
outFile<<"随机生成的二维点对为:\n";
for(int i=0;i<length;i++){
X[i].ID=i;
X[i].x=Random();
X[i].y=Random();
cout<<"("<<X[i].x<<","<<X[i].y<<") ";
outFile<<"("<<X[i].x<<","<<X[i].y<<") \n";
}
xPosition a;
xPosition b;
float d;
start=clock();
Cpair2(X,length,a,b,d);
finish=clock();
cout<<endl;
cout<<"最邻近点对为:("<<a.x<<","<<a.y<<")和
("<<b.x<<","<<b.y<<") "<<endl;
outFile<<"最邻近点对为:("<<a.x<<","<<a.y<<")和
("<<b.x<<","<<b.y<<") \n";
cout<<"最邻近距离为: "<<d<<endl;
outFile<<"最邻近距离为: "<<d<<"\n";
cout<<"程序运行时间:"<<finish-start<<endl;
outFile<<"程序运行时间:"<<finish-start;
outFile.close();
4.求解最短距离:
将总的点对分为三部分,对每一部分求解最短的距离,对只有两对、三对的情况直接进行距离求解。

当对每一部分求解最短距离时,采用分治法分解为一个个小的子问题,
对点在两个区域的情况,依照思想,进行排序比较,和已有的最短距离比较,最终确定最短距离的点对。

代码实现:
void closest(xPosition X[],yPosition Y[],yPosition Z[],int
left,int right,xPosition& a,xPosition& b,float& d){
if(right-left==1) //两点的情形
{
a=X[left];
b=X[right];
d=dis(X[left],X[right]);
return;
}
if(right-left==2) //3点的情形
{
float d1=dis(X[left],X[left+1]);
float d2=dis(X[left+1],X[right]);
float d3=dis(X[left],X[right]);
if(d1<=d2 && d1<=d3){
a=X[left];
b=X[left+1];
d=d1;
return;
}
if(d2<=d3){
a=X[left+1];
b=X[right];
d=d2;
}
else{
a=X[left];
b=X[right];
d=d3;
}
return;
}
//多于3点的情形,用分治法
int m=(left+right)/2;
int f=left,g=m+1;
for(int i=left;i<=right;i++){
if(Y[i].p>m) Z[g++]=Y[i];
else Z[f++]=Y[i];
}
closest(X,Z,Y,left,m,a,b,d);
float dr;
xPosition ar,br;
closest(X,Z,Y,m+1,right,ar,br,dr);
{
a=ar;
b=br;
d=dr;
}
Merge(Z,Y,left,m,right);//重构数组Y
int k=left;
for(int i=left;i<=right;i++){
if(fabs(X[m].x-Y[i].x)<d){
Z[k++]=Y[i];
}
}
//搜索Z[l:k-1]
for(int i=left;i<k;i++){
for(int j=i+1;j<k && Z[j].y-Z[i].y<d;j++){
float dp=dis(Z[i],Z[j]);
if(dp<d){
d=dp;
a=X[Z[i].p];
b=X[Z[j].p];
}
}
}
}
四.实验数据分析:
本实验对不同规模的数据进行测试,实验数据如下。

五.实验感受:
在实验中,随机生成一定数量的点对,对这些点对进行最短距离求解,由于设置的范围过小,在进行时间测量时,得到的数据都为零,故在进行实际分析时,需要使用大规模的数据。

相关主题