求平面最小点距的算法设计

平面上有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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔塔o

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值