平面最接近点对问题(分治法)
问题描述参见:https://www.cnblogs.com/zyxStar/p/4591897.html
代码参考:http://blog.csdn.net/qq_28666193/article/details/53351482(原代码中有几处错误,我作了修改)
头文件部分:
(1)数据结构部分:
//涉及的数据结构 #ifndef DATASET_H #define DATASET_H struct point{ //点结构 double x, y; }; #endif
(2)函数声明部分:
//函数头文件 //======================================= #ifndef FUNC_H #define FUNC_H #include "dataset.h" double closest_distance(point s[], int low, int high, point rec[]); double Distance(point a, point b); bool comp_x(point a, point b); bool comp_y(point a, point b); #endif
源文件部分:
(1)函数实现部分:
//求解最近距离的函数实现 #include "dataset.h" #include <math.h> #include <algorithm> using namespace std; double Distance(point a, point b) //计算两点距离 { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) - (a.y - b.y)); } bool comp_x(point a, point b) //按x升序判别函数 { return a.x < b.x; } bool comp_y(point a, point b) //按y升序判别函数 { return a.y < b.y; } //函数实现:rec[]存储最接近点对; double closest_distance(point s[], int low, int high, point rec[]) { double d1, d2, d3, d; int mid, i, j, index; double x1, y1, x2, y2; //记录最近的点对 point *P = new point[high - low + 1]; point temp_1[2], temp_2[2], temp_3[2]; if (high - low == 1) //两个点时的情况 { rec[0].x = s[low].x; rec[0].y = s[low].y; rec[1].x = s[high].x; rec[1].y = s[high].y; return Distance(s[low], s[high]); } if (high - low == 2) //三个点时的情况 { d1 = Distance(s[low], s[low + 1]); d2 = Distance(s[low + 1], s[high]); d3 = Distance(s[low], s[high]); if ((d1 <= d2) && (d1 <= d3)) //这里在判断三种情况时,第二种情况没必要使用(d2<d3)&&(d2<d1),相较更繁琐了; { rec[0].x = s[low].x; rec[0].y = s[low].y; rec[1].x = s[low + 1].x; rec[1].y = s[low + 1].y; return d1; } else if (d2 < d3) { rec[0].x = s[low + 1].x; rec[0].y = s[low + 1].y; rec[1].x = s[high].x; rec[1].y = s[high].y; return d2; } else { rec[0].x = s[low].x; rec[0].y = s[low].y; rec[1].x = s[high].x; rec[1].y = s[high].y; return d3; } } mid = (low + high) / 2; d1 = closest_distance(s, low, mid, rec); temp_1[0] = rec[0]; temp_1[1] = rec[1]; d2 = closest_distance(s, mid + 1 ,high, rec); temp_2[0] = rec[0]; temp_2[1] = rec[1]; if (d1 <= d2) { d = d1; rec[0] = temp_1[0]; rec[1] = temp_1[1]; } else { d = d2; rec[0] = temp_2[0]; rec[1] = temp_2[1]; } index = 0; for (i = mid; (i >= low) && ((s[mid].x - s[i].x) < d); i--) { P[index++] = s[i]; //点集合P1 } for (i = mid + 1; (i <= high) && ((s[i].x - s[mid].x) < d); i++) { P[index++] = s[i]; //点集合P2 } sort(P, P + index, comp_y); //升序排列 for (i = 0; i < index; i++) { for (j = i + 1; j < index; j++) { if ((P[j].y - P[i].y) >= d) break; else { d3 = Distance(P[i], P[j]); if (d3 < d) { rec[0].x = P[i].x; rec[0].y = P[i].y; rec[1].x = P[j].x; rec[1].y = P[j].y; d = d3; } } } } delete []P; //注意动态内存的删除方式,防止内存泄漏 return d; }
(2)主函数部分:
//2018_02_24 //使用分治法求解二维平面最接近点问题 //============================================================= #include <iostream> #include <math.h> #include <algorithm> #include "dataset.h" //数据结构实现放在这个头文件中 #include "func.h" //函数声明的头文件 using namespace std; int main(void) { point p[10]; //设定点的集合 int n; double minDist; cout << "输入点的个数:\n"; cin >> n; cout << "输入点集:(x , y) \n"; for (int i = 0; i < n; i++) cin >> p[i].x >> p[i].y; sort(p, p + n, comp_x); //对输入的点先进行排序 point index[2]; minDist = closest_distance(p, 0, n - 1, index); cout << "最小距离点对为:(" << index[0].x << "," << index[0].y << "),(" << index[1].x << "," << index[1].y << ")"; cout << "最小距离为:\n" << minDist; system("pause"); return 0; }
最后,结果如下: