平面最接近點對問題(分治法)
阿新 • • 發佈:2018-02-25
技術 src void emp image mage tar 分治 pac
問題描述參見: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; }
最後,結果如下:
平面最接近點對問題(分治法)