最近对问题(分治法)

#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;


struct point
{
double x, y;
};
double Distance(point a, point b);//声明函数,否则在c++中会出现“找不到标示符”的错误
double ClosestDistance(point s[], int low, int high)
{
int num,mid,index=0;
double d,d1, d2, d3;
point p[20];
num = high - low;
if (num == 1)//说明只有两个点,直接返回距离即是最近的
return Distance(s[low], s[high]);
else if (num == 2)//说明有三个点,求出两两点的最近值
{
d1 = Distance(s[low], s[low + 1]);
d2 = Distance(s[low], s[high]);
d3 = Distance(s[low+1], s[high]);
d=(d1 < d2) ? ((d1<d3) ? d1 : d3) : ((d2>d3) ? d3 : d2);//比较三个值得大小,将最小的赋值给d
return d;
}
else
{
mid = 0.5*(low + high);
d1=ClosestDistance(s, low, mid);//在mid的左边的最近值
d2 = ClosestDistance(s, mid+1, high);//在mid的左边的最近值,注意的是当mid的点在左边算上的时候在右边就不要在算了,不然就会导致结果错误
if (d1 <=d2)
{
d = d1;
}
else
{
d = d2;
}


//以下是解决求在跨区域中的两个点的最近值
//首先可以根据已经求得的在两边的最近值排除一部分的点
//即是,当两个点的X座标的距离大于d的点将不再参与该轮的比较,因为显然它不可能是最近点对了


for (int i = low; (i <=mid) && (s[mid].x-s[i].x < d); i++)//到mid的x座标小于d的点的集合
{
p[index++] = s[i];
}
for (int i = mid+1; (i <= high) && (s[i].x - s[mid].x < d); i++)
{
p[index++] = s[i];
}
//可以进行对y座标的升序的排序,方便排除一些点
for (int i = 0; i <= index; i++)
{
for (int j = i + 1; j < index; j++)
{
if (abs(s[i].y - s[j].y)>d)//两点的y座标的差大于d,那就也不用比了
break;
else
{
d3 = Distance(s[i], s[j]);
d = (d < d3) ? d : d3;
}
}
}
return d;//返回最近的值d
}
}
double Distance(point a, point b)
{
double d=sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
return d;
}
int main(int argc, _TCHAR* argv[])
{
double d;
int i,n;
point p[50];//将数组的大小设的大些,防止在下面发生溢出
cout << "输入点的对数:n=" ;
cin >> n;
for (i = 0; i < n; i++)//将输入的值一次赋值到数组中
{
cout<< "x" << i << "=";
cin >> p[i].x;
cout << "y" << i << "=";
cin >> p[i].y;
cout << endl;
}
d=ClosestDistance(p, 0, n-1);
cout << "最近距离是" << d << endl;
}
点赞