平面上有n个点P1、P2、…Pi、…、Pn,n>1,Pi的坐标为(Xi,Yi)。请设计两种算法求距离最近的两个点及两者之间的距离,并分析两种算法的时间复杂度。
要求算法测试时,点的个数不能少于10个。
提示:为保持与教材P34中算法参数的一致性,输入可采用3个数组,即:PN[]表示点的编号集合,PX[]表示对应X坐标,PY[]表示对应Y的坐标;输出可以建立一个结构体,分别对应两个点的编号及对应的距离。以下是10个点的例子,其中点坐标都设为整数,可以用来做算法测试。
int PN[10]={0,1,2,3,4,5,6,7,8,9};
int PX[10]={-11,15,4,-5,2,3,-2,-7,-4,10};
int PY[10]={4,-3,6,-6,-1,2,7,5,-7,0};
另外,结构体可以采取如下定义:
typedef struct pS{
int iC1,iC2; //点的编号
float fD; //两点距离
} pT;
代码:
#include<stdio.h> #include<stdlib.h> #include<math.h> #define MAX 99999 //方法一:蛮力算法 double closestPoints(double x[],double y[],int n){ double x1,x2,y1,y2; //记录下标 double distance,minDistance=MAX; int i,j; for(i=0;i<n;i++) for(j=i+1;j<n;j++){ distance=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]); //计算距离 if(distance<minDistance){ minDistance=distance; x1=x[i];y1=y[i]; x2=x[j];y2=y[j]; } } printf("最近点对为:(%f,%f)-(%f,%f)\n",x1,y1,x2,y2); //输出坐标 return minDistance; } int main(){ double x[100],y[100]; double minDistance; int n,i; /*printf("输入点的个数:\n"); scanf("%d",&n); printf("输入点集的坐标:\n"); for(k=0;k<n;k++){ scanf("%lf%lf",&x[k],&y[k]); }*/ double PX[10]={-11,15,4,-5,2,3,-2,-7,-4,10}; double PY[10]={4,-3,6,-6,-1,2,7,5,-7,0}; printf("十个点的坐标如下:\n"); for(i=0;i<10;i++){ printf("(%f,%f)\n",PX[i],PY[i]); } minDistance=closestPoints(PX,PY,10); printf("其距离为:%f\n",sqrt(minDistance)); return 0; } 方法二:分治法 #include <stdio.h> #include <math.h> //Point 是一个点的结构体,x,y表示横纵坐标 typedef struct Point{ float x; float y; }Point; //求两点距离的函数 float distance(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } //快排 int partition(Point a[],int begin,int end){ Point key = a[end]; int i = begin-1; for(int j=begin;j<end;j++){ if(a[j].x<=key.x){ i++; Point temp = a[i]; a[i] = a[j]; a[j] = temp; } } i++; a[end] = a[i]; a[i] = key; return i; } void quiksort(Point a[],int begin,int end){ if(begin<end){ int middle = partition(a,begin,end); quiksort(a,begin,middle-1); quiksort(a,middle+1,end); } } //分治法求解距离 float closest (Point* points,int n,Point &a, Point &b){ //递归函数出口,两个点直接返回距离,一个点返回一个最大值 if(n==2){ a = points[0]; b = points[1]; return distance(a,b); } else if(n<2){ return 99999; } //分治 else{ int n1 = n/2; int n2 = n-n1; float d1,d2,dis,mid; Point points1 [n1]; Point points2 [n2]; Point a1,a2,b1,b2; //按x坐标排点对 quiksort(points,0,n-1); mid = points[n1].x; for(int i=0;i<n1;i++){ points1[i] = points[i]; } for(int i=0;i<n2;i++){ points2[i] = points[i+n1]; } //左右两个分区 d1 = closest(points1,n1,a1,b1); d2 = closest(points2,n2,a2,b2); if(d1<=d2){ a = a1; b = b1; dis = distance(a,b); } else{ a = a2; b = b2; dis = distance(a,b); } //中间区域 Point points3[n]; int k = -1; for(int i=0;i<n;i++){ if(abs(points[i].x-mid)<=dis){ points3[++k] = points[i]; } } for(int i=0;i<n;i++){ for(int j=i+1;j<i+7&&j<k;j++){ if(distance(points3[i],points3[j])<dis){ a = points3[i]; b = points3[j]; dis = distance(a,b); } } } return dis; } } int main(void){ Point PN[10]={0,1,2,3,4,5,6,7,8,9}; int PX[10]={-11,15,4,-5,2,3,-2,-7,-4,10}; int PY[10]={4,-3,6,-6,-1,2,7,5,-7,0}; /*for(int i=0;i<2;i++){ scanf("%lf%lf",&points[i].x,&points[i].y); }*/ for(int i=0;i<10;i++){ PN[i].x=PX[i]; PN[i].y=PY[i]; printf("(%f,%f)\n",PN[i].x,PN[i].y); } Point a,b; float disance = closest(PN,10,a,b); printf("最近点对为:(%f,%f)-(%f,%f)\n",a.x,a.y,b.x,b.y); printf("距离%f",disance); }