#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;
}
divide-conquer 递归查找最小距离 closest-pair algorithm
最新推荐文章于 2021-04-13 21:35:06 发布