存在n个点,如果用穷举所有距离(N(N-1)/2个点对),时间辅助度为O(nlogn)。书上有严格的证明能分治在nlogn的时间界完成。
- #include <iostream>
- #include <algorithm>
- using namespace std;
- #define MAXN 100
- struct Point//点结构体
- {
- double x, y;
- };
- //得到两个点的距离
- double Distance(Point a, Point b)
- {
- double s;
s = sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
- return s;
- }
- //按x排序
- bool cmp1(Point a, Point b)
- {
- return a.x < b.x;
- }
- //按y排序
- bool cmp2(Point a, Point b)
- {
- return a.y < b.y;
- }
- //计算最小距离函数(分治)
- double ClosePoints(Point s[], int low, int high, Point rec[])//传入点集数组,low,high和保存两个点的结果数组rec
- {
- double d1, d2, d3, d;//左边右边中间最小距离
- int mid, i, j, index;//index代表在中间距离在d内的点集
- double x1, y1, x2, y2;
- Point p[MAXN], temp1[2], temp2[2], temp3[2];//p保存mid左右两边小于d的点集
- 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(rec[0], rec[1]);
- }
- 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)
- {
- 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 < d1&&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 if (d3 < d1&&d3 < d2)
- {
- 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 = ClosePoints(s, low, mid, rec);//左递归
- temp1[0] = rec[0];//保存左边结果数组
- temp1[1] = rec[1];
- d2 = ClosePoints(s, mid + 1, high, rec);//右递归
- temp2[0] = rec[0];//保存右边结果数组
- temp2[1] = rec[1];
- //找到最小的距离在左边还是在右边
- if (d1 < d2)
- {
- d = d1;
- rec[0] = temp1[0];
- rec[1] = temp1[1];
- }
- else
- {
- d = d2;
- rec[0] = temp2[0];
- rec[1] = temp2[1];
- }
- index = 0;
- //遍历mid的两边找到小于d的点集保存在p数组中
- for (i = mid; (i >= low) && (s[mid].x - s[i].x) < d; i--)
- {
- p[index++] = s[i];
- }
- for (i = mid; (i <= high) && (s[i].x - s[mid].x) < d; i++)
- {
- p[index++] = s[i];
- }
- sort(p, p + index, cmp2);//按y排序
- for (i = 0; i < index; i++)//遍历p数组中的点集
- {
- for (j = i + 1; j < i + 7 && j < index; j++)//遍历每个p[i]点的周围小于d的点(最多有7个点(能证明))
- {
- if ((p[j].y - p[i].y) > d)break;//大于d跳过
- 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;
- }
- }
- }
- }
- return d;//返回最小距离
- }
- int main()
- {
- Point p[MAXN];
- int n;
- cin >> n;
- for (int i = 0; i < n; i++)
- {
- p[i].x = rand() % 100;
- p[i].y = rand() % 100;
- cout << "(" << p[i].x << "," << p[i].y << ") ";
- }
- sort(p, p + n, cmp2);//按x坐标排序
- cout << endl;
- for (int i = 0; i < n; i++)
- {
- cout << "(" << p[i].x << "," << p[i].y << ") ";
- }
- cout << endl;
- Point rec[2];
- int mindistance = ClosePoints(p, 0, n - 1, rec);
- cout << "(" << rec[0].x << "," << rec[0].y << ") ";
- cout << "(" << rec[1].x << "," << rec[1].y << ")";
- cout << endl;
- cout << mindistance << endl;
- return 0;
- }