divide-conquer 递归查找最小距离 closest-pair algorithm

#include<iostream>
#include<vector>
#include<string>
using namespace std;
/************************************************************************/
/* 程序功能:采用closestPair算法,求解点集中最小距离                              */
/************************************************************************/
/************************************************************************/
/* 全局结构定义                                                                     */
/************************************************************************/
struct point 
{
	float x;
	float y;
} ;
/************************************************************************/
/* 预定义参数                                                                     */
/************************************************************************/
#define POINTNUMBER 8
#define NEG_INFINITE -1000
#define POS_INFINITE  1000
/************************************************************************/
/* 预定义的内联函数                                                                     */
/************************************************************************/
#define min(x,y)   (x<=y)?x:y
/************************************************************************/
/* 函数原型声明                                                                     */
/************************************************************************/
void input(vector<point>&pointCrowd );
void sortPointByXY(vector<point>&pointCrowd,int l,int r,string xy);
void mergeSort(vector<point>&pointCrowd,int l,int m,int r,string xy);
vector<point> getPointsInRange(vector<point>points,float low,float high,string xy);
double calDistance(point p1,point p2);
double getMinDistance(vector<point>&pointCrowd);
double mainFuncton(vector<point>crowd);
/************************************************************************/
/* 程序入口主函数                                                                     */
/************************************************************************/
int main()
{
	vector<point> pointCrowd;
	input(pointCrowd);
	cout<<"min distance:"<<mainFuncton(pointCrowd)<<endl;
	system("pause");
}
/************************************************************************/
/* 实现递归查找最小点间距的主函数                                                                     */
/************************************************************************/
double mainFuncton(vector<point>crowd)
{
	//递归停止条件
	if (crowd.size() <= 2)
	{
		return getMinDistance(crowd);
	}
	//第一步:对所有点按x排序
	sortPointByXY(crowd,0,crowd.size()-1,string("x"));
	//计算出中间分割线
	float cutByx = (crowd[crowd.size()/2].x+crowd[(crowd.size()/2)-1].x)/2;
	//获取当前点集中最小x坐标和最大x坐标
	float min_X = crowd.front().x;
	float max_X = crowd.back().x;
	//左边按x递增排列的点集
	vector<point>subLeftCrowd = getPointsInRange(crowd,min_X,cutByx,string("x"));
	double delta1 = mainFuncton(subLeftCrowd);
	//右边按x递增排列的点集
	vector<point>subRightCrowd = getPointsInRange(crowd,cutByx,max_X,string("x"));
	double delta2 = mainFuncton(subRightCrowd);
	//左边和右边的最小距离
	double delta = min(delta1,delta2);
	/*计算分界线处最小距离*/
	//获取分界线处附近所有点
	vector<point> subMiddleCrowd = getPointsInRange(crowd,cutByx-delta,cutByx+delta,string("x"));
	//将分界线处所有点按y排列
	sortPointByXY(subMiddleCrowd,0,subMiddleCrowd.size()-1,string("y"));
	//计算分界线处点距最小值:规则1:最多计算其后11个点 规则2:只计算分布在分界线两侧的点
	double minSubMiddleCrowd = POS_INFINITE;
	for (auto i =subMiddleCrowd.begin();i !=subMiddleCrowd.end();i++ )
	{
		for(auto j =i+1;(j !=(i+12) )&&(j !=subMiddleCrowd.end());j++)
		{
			if ((i->x-cutByx>=0)&& (j->x-cutByx<=0) || (i->x-cutByx<=0)&& (j->x-cutByx>=0) )
			{
				double temp = calDistance(*i,*j);
				if (temp<minSubMiddleCrowd)
				{
					minSubMiddleCrowd = temp;
				}
			}
		}
	}
	return  min(minSubMiddleCrowd,delta);
}

/************************************************************************/
/* 函数功能:输入待检测点
	输入参数:存储点集的容器 vector<point>&pointCrowd
	返回参数:void*/
/************************************************************************/
void input(vector<point>&pointCrowd )
{
	cout<<"input "<<POINTNUMBER<<" Points: x,y"<<endl;
	point pcrowd[POINTNUMBER] ={{-5,-5},{-4,-4},{-3,-3},{-3,-6},{-2,-3},{-1,-5},{0,-3},{1,-4}};
	for (auto i = 0 ;i< POINTNUMBER;i++)
	{
		//point p;
		//cin>>p.x>>p.y;
		pointCrowd.push_back(pcrowd[i]);
	}
}
/************************************************************************/
/* 函数功能:对存储点集的容器 vector<point>&pointCrowd里面的点按x递增进行排序(归并排序)
	输入参数:存储点集的容器 vector<point>&pointCrowd
	返回参数:void*/
/************************************************************************/
void sortPointByXY(vector<point>&pointCrowd,int l,int r,string xy)
{
	if (l<r)
	{
		int m = (l+r)/2;
		sortPointByXY(pointCrowd,l,m,xy);
		sortPointByXY(pointCrowd,m+1,r,xy);
		mergeSort(pointCrowd,l,m,r,xy);
	}
}
/************************************************************************/
/* 函数功能:对两个有序的点列,按X或Y由小到大合并
	输入参数:存储点集的容器 vector<point>&pointCrowd
	返回参数:void*/
/************************************************************************/

void mergeSort(vector<point>&pointCrowd,int l,int m,int r,string xy)
{
	vector<point> L (pointCrowd.begin()+l,pointCrowd.begin()+m+1);
	vector<point> R(pointCrowd.begin()+m+1,pointCrowd.begin()+r+1);
	int p=0,q=0; 
	while(p !=L.size() && q != R.size())
	{
		if (xy ==string("x"))
		{
			if (L[p].x<R[q].x)
			{
				pointCrowd[l++] = L[p];
				p++;
			}
			else
			{
				pointCrowd[l++] =R[q];
				q++;
			}
		}
		else
		{
			if (L[p].y<R[q].y)
			{
				pointCrowd[l++] = L[p];
				p++;
			}
			else
			{
				pointCrowd[l++] =R[q];
				q++;
			}
		}

	}
	while (p !=L.size())
	{
		pointCrowd[l++] = L[p++];
	}
	while (q != R.size())
	{
		pointCrowd[l++] =R[q++];
	}
}

/************************************************************************/
/* 函数功能:根据给定的X或Y的范围,取出容易中在范围的所有点,并按从小到大排序
	输入参数:存储点集的容器 vector<point>&pointCrowd
	返回参数:vector<point>*/
/************************************************************************/
vector<point> getPointsInRange(vector<point>points,float low,float high,string xy)
{
	vector<point> result;
	if (xy == string("x"))
	{
		//按x排序
		sortPointByXY(points,0,points.size()-1,string("x"));
	}
	else
	{
		//按y排序
		sortPointByXY(points,0,points.size()-1,string("y"));
	}
	for (auto i = points.begin();i != points.end();i++)
	{
		if (xy == string("x"))
		{
			if (i->x >=low && i->x <=high)
			{
				result.push_back(*i);
			}
		}
		if (xy == string("y"))
		{
			if (i->y >=low && i->y <=high)
			{
				result.push_back(*i);
			}
		}
	}
	return result;
}
/************************************************************************/
/* 函数功能:计算任意给定两点的间距
	输入参数:两个点point1,point2
	返回参数:double*/
/************************************************************************/
double calDistance(point p1,point p2)
{
	return sqrt(pow(p1.x-p2.x,2)+pow(p1.y-p2.y,2));
}
/************************************************************************/
/* 函数功能:获取给定点集中距离最小值
	输入参数:存储点集的容器 vector<point>&pointCrowd
	返回参数:double*/
/************************************************************************/
double getMinDistance(vector<point>&pointCrowd)
{
	double Min = POS_INFINITE;
	for(auto i=pointCrowd.begin();i != pointCrowd.end();i++)
	{
		for(auto j =i+1;j != pointCrowd.end();j++)
		{
			double temp = calDistance(*i,*j);
			if (temp<Min)
			{
				Min = temp;
			}
		}
	}
	return Min;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值