1. 程式人生 > >平面最接近點對問題(分治法)

平面最接近點對問題(分治法)

技術 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;
}

最後,結果如下:

技術分享圖片

平面最接近點對問題(分治法)