Skip to content

Commit

Permalink
平面最接近点对
Browse files Browse the repository at this point in the history
最优二叉搜索树
  • Loading branch information
StupidRabbit29 committed Dec 18, 2019
1 parent e5d2e6f commit a22e5d5
Show file tree
Hide file tree
Showing 13 changed files with 2,141 additions and 1 deletion.
20 changes: 20 additions & 0 deletions Algorithm.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "最长单调递增子序列
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "钢条切割-DP", "钢条切割-DP\钢条切割-DP.vcxproj", "{D99EF451-8F9F-4733-8346-93CE93CD613B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "平面最近点对-DC", "平面最近点对-DC\平面最近点对-DC.vcxproj", "{B29E11B8-7A69-4F77-A3DE-AE90E0537A66}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "最优二叉搜索树-DC", "最优二叉搜索树-DC\最优二叉搜索树-DC.vcxproj", "{6FC003B5-3D41-4A1D-98D5-3AE05E37C232}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Expand Down Expand Up @@ -41,6 +45,22 @@ Global
{D99EF451-8F9F-4733-8346-93CE93CD613B}.Release|x64.Build.0 = Release|x64
{D99EF451-8F9F-4733-8346-93CE93CD613B}.Release|x86.ActiveCfg = Release|Win32
{D99EF451-8F9F-4733-8346-93CE93CD613B}.Release|x86.Build.0 = Release|Win32
{B29E11B8-7A69-4F77-A3DE-AE90E0537A66}.Debug|x64.ActiveCfg = Debug|x64
{B29E11B8-7A69-4F77-A3DE-AE90E0537A66}.Debug|x64.Build.0 = Debug|x64
{B29E11B8-7A69-4F77-A3DE-AE90E0537A66}.Debug|x86.ActiveCfg = Debug|Win32
{B29E11B8-7A69-4F77-A3DE-AE90E0537A66}.Debug|x86.Build.0 = Debug|Win32
{B29E11B8-7A69-4F77-A3DE-AE90E0537A66}.Release|x64.ActiveCfg = Release|x64
{B29E11B8-7A69-4F77-A3DE-AE90E0537A66}.Release|x64.Build.0 = Release|x64
{B29E11B8-7A69-4F77-A3DE-AE90E0537A66}.Release|x86.ActiveCfg = Release|Win32
{B29E11B8-7A69-4F77-A3DE-AE90E0537A66}.Release|x86.Build.0 = Release|Win32
{6FC003B5-3D41-4A1D-98D5-3AE05E37C232}.Debug|x64.ActiveCfg = Debug|x64
{6FC003B5-3D41-4A1D-98D5-3AE05E37C232}.Debug|x64.Build.0 = Debug|x64
{6FC003B5-3D41-4A1D-98D5-3AE05E37C232}.Debug|x86.ActiveCfg = Debug|Win32
{6FC003B5-3D41-4A1D-98D5-3AE05E37C232}.Debug|x86.Build.0 = Debug|Win32
{6FC003B5-3D41-4A1D-98D5-3AE05E37C232}.Release|x64.ActiveCfg = Release|x64
{6FC003B5-3D41-4A1D-98D5-3AE05E37C232}.Release|x64.Build.0 = Release|x64
{6FC003B5-3D41-4A1D-98D5-3AE05E37C232}.Release|x86.ActiveCfg = Release|Win32
{6FC003B5-3D41-4A1D-98D5-3AE05E37C232}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
273 changes: 273 additions & 0 deletions 平面最近点对-DC/FB.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
#include<iostream>
#include<vector>
#include<algorithm>
#include<ctime>
#include<fstream>
#include<sstream>
using namespace std;

#define PointX_NUM 1032 //数据个数//1032

class PointX
{
public:
PointX() { ID = 0; x = 0.0; y = 0.0; }
PointX(int ID, double x, double y);
~PointX();
int ID;
double x, y; //经度和纬度
friend ostream& operator<<(ostream& os, const PointX& p); //重载cout
bool operator <=(PointX a)const
{
return x <= a.x;
}
bool operator <(PointX a)const
{
return x < a.x;
}
private:

};

class PointY
{
public:
PointY() { ID = 0; x = 0.0; y = 0.0; }
PointY(int ID, double x, double y);
~PointY();
int ID;
double x, y; //经度和纬度
friend ostream& operator<<(ostream& os, const PointY& p); //重载cout
bool operator <=(PointY a)const
{
return y <= a.y;
}
bool operator <(PointY a)const
{
return y < a.y;
}
private:

};

PointX::PointX(int ID, double x, double y)
{
this->ID = ID;
this->x = x;
this->y = y;
}

PointX::~PointX()
{
}

PointY::PointY(int ID, double x, double y)
{
this->ID = ID;
this->x = x;
this->y = y;
}

PointY::~PointY()
{
}

ostream& operator<<(ostream& os, const PointX& p)
{
cout.precision(10); // 设置输出精度
os << "ID:" << p.ID << " (" << p.x << "," << p.y << ")";
return os;
}
ostream& operator<<(ostream& os, const PointY& p)
{
cout.precision(10); // 设置输出精度
os << "ID:" << p.ID << " (" << p.x << "," << p.y << ")";
return os;
}


bool Cpair2(PointX X[], PointY Y[], PointY Z[], int n, PointX& a, PointX& b, double& d);//平面最近点对
void closest(PointX X[], PointY Y[], PointY Z[], int l, int r, PointX& a, PointX& b, double& d);//X以x坐标排序的点,Y以y坐标排序的点,Z存放分界线范围内的点 ,l左端点,r右端点(包含r),a,b是两个最近的点,d最短距离
template<class Type> inline double distance(const Type& u, const Type& v);
template <class Type> void Merge(Type a[], Type b[], int l, int m, int r);//a[]待排数组,b[]目标数组,三个参数分别是数组下标left,middle,right,包含right


int main()
{
clock_t start_time = clock();

PointX* X = new PointX[(int)PointX_NUM];
PointY* Y = new PointY[(int)PointX_NUM];
PointY* Z = new PointY[(int)PointX_NUM];
ifstream fs("data2.txt", ios::in);
if (!fs) {
cout << "打开文件失败"; return 0;
}
int cnt = 0;
string lineStr;
char ch;
for (int i = 0; getline(fs, lineStr); i++)
{
stringstream ss(lineStr);
ss >> X[i].ID >> ch >> X[i].x >> ch >> X[i].y;
stringstream ss1(lineStr);
ss1 >> Y[i].ID >> ch >> Y[i].x >> ch >> Y[i].y;
}

fs.close();

PointX a, b;
double d;
Cpair2(X, Y, Z, PointX_NUM, a, b, d);
cout << "最近点对是:" << endl << a << "\t" << b << endl << "最短距离是:" << d << endl;

delete[] X;
delete[] Y;
delete[] Z;

clock_t end_time = clock();
cout << endl << "Running time is: " << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 << "ms" << endl;
//CLOCKS_PER_SEC表示一秒钟内CPU运行的时钟周期数,用于将clock()函数的结果转化为以秒为单位的量

system("pause");
return 0;
}

//计算平面上两点间距离
template<class Type>
inline double distance(const Type& u, const Type& v)
{
double dx = u.x - v.x;
double dy = u.y - v.y;
return sqrt(dx * dx + dy * dy);
}

//归并排序
template <class Type>
void Merge(Type a[], Type b[], int l, int m, int r)
//a[]待排数组,b[]目标数组,三个参数分别是数组下标left,middle,right,包含right
{
int i = l, j = m + 1, k = l;//i左子数组起点,j右子数组起点,k辅助数组起点
while ((i <= m) && (j <= r))
{
if (a[i] <= a[j])
b[k++] = a[i++];
else
b[k++] = a[j++];
}
/*将剩余元素直接拷贝到b*/
if (i > m)//左子段空了,右子段有剩余元素
while (j <= r)
b[k++] = a[j++];
else
while (i <= m)//左子段有剩余元素
b[k++] = a[i++];
}

bool Cpair2(PointX X[], PointY Y[], PointY Z[], int n, PointX& a, PointX& b, double& d)
{
if (n < 2) return false;
sort(X, X + n);
sort(Y, Y + n);
closest(X, Y, Z, 0, n - 1, a, b, d);
return true;
}

void closest(PointX X[], PointY Y[], PointY Z[], //X以x坐标排序的点,Y以y坐标排序的点,Z存放分界线范围内的点
int l, int r, PointX& a, PointX& b, double& d)//l左端点,r右端点(包含r),a,b是两个最近的点,d最短距离
{
if (r - l == 1)//两点
{
a = X[l];
b = X[r];
d = distance(a, b);
return;
}
if (r - l == 2)//三点
{
double d1 = distance(X[l], X[l + 1]);
double d2 = distance(X[l + 1], X[r]);
double d3 = distance(X[l], X[r]);
if (d1 <= d2 && d1 <= d3)
{
a = X[1];
b = X[l + 1];
d = d1;
return;
}
else if (d2 <= d1 && d2 <= d3)
{
a = X[l + 1];
b = X[r];
d = d2;
return;
}
else
{
a = X[l];
b = X[r];
d = d3;
return;
}
}

/*多于三点,用分治法*/
int m = (l + r) / 2;//m是中位数
int f = l, g = m + 1;//f,g分别是左半段和右半段下标起点
PointY tempP[PointX_NUM];
int tempI = 0;
for (int i = l; i <= r; i++)//将Y[]在分界线(x中位数)左边的放在Z左半段,否则右半段
{//Z[]存放p1到p2内按y坐标排序的点

if (Y[i].x < X[m].x) Z[f++] = Y[i];
else if (Y[i].x > X[m].x) Z[g++] = Y[i];
else//相等,先暂时放在tempI数组里,等到分完所有元素后再用tempI数组里的元素填充满数组,使两个数组大小一样。
{
tempP[tempI++] = Y[i];
}
}
for (int i = 0; i < tempI; i++)
{
if (f <= m)//左边还没满,放左边
Z[f++] = tempP[i];
else if (g <= r)//左边满了右边没满,放右边
Z[g++] = tempP[i];
else
cerr << "Z[] array error";
}

closest(X, Z, Y, l, m, a, b, d);//求左半段最小距离
double dr;//右边最短距离
PointX ar, br;
closest(X, Z, Y, m + 1, r, ar, br, dr);
if (dr < d)//取左段和右段较小者
{
a = ar;
b = br;
d = dr;
}

Merge(Z, Y, l, m, r);//将Z里的两段数组合并放回Y

int k = l;
for (int i = l; i <= r; i++)//将分界线2d范围内的点拷到Z数组
{
if (fabs(Y[m].x - Y[i].x <= d)) //好像可以取等?
Z[k++] = Y[i];
}
for (int i = l; i < k; i++)//遍历分界线区域内的点,计算距离//不能取等
{
for (int j = i + 1; j < k && Z[j].y - Z[i].y < d; j++)//对于点Z[i],计算其上距离在d内的点于它的距离
{
double dp = distance(Z[j], Z[i]);
if (dp < d)//取两段和中间距离较小者
{
d = dp;
PointX tempA(Z[i].ID, Z[i].x, Z[i].y), tempB(Z[j].ID, Z[j].x, Z[j].y);
a = tempA;
b = tempB;
}
}
}
}

Loading

0 comments on commit a22e5d5

Please sign in to comment.