数据结构和算法分析10.16(计算点对)

本文探讨了在N个点中寻找最短距离的点对问题,通过使用分治策略,实现了一个时间复杂度为O(nlogn)的高效算法。该算法首先对点集进行排序,然后递归地将问题分解为更小的子问题,最后在子问题解决方案的基础上,检查中间区域可能存在的更短距离,确保找到全局最小距离。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

存在n个点,如果用穷举所有距离(N(N-1)/2个点对),时间辅助度为O(nlogn)。书上有严格的证明能分治在nlogn的时间界完成。

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. #define MAXN 100
  5. struct Point//点结构体
  6. {
  7.     double x, y;
  8. };
  9. //得到两个点的距离
  10. double Distance(Point a, Point b)
  11. {
  12.     double s;

    s = sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));

  1.     return s;
  2. }
  3. //按x排序
  4. bool cmp1(Point a, Point b)
  5. {
  6.     return a.x < b.x;
  7. }
  8. //按y排序
  9. bool cmp2(Point a, Point b)
  10. {
  11.     return a.y < b.y;
  12. }
  13. //计算最小距离函数(分治)
  14. double ClosePoints(Point s[], int low, int high, Point rec[])//传入点集数组,low,high和保存两个点的结果数组rec
  15. {
  16.     double d1, d2, d3, d;//左边右边中间最小距离
  17.     int mid, i, j, index;//index代表在中间距离在d内的点集
  18.     double x1, y1, x2, y2;
  19.     Point p[MAXN], temp1[2], temp2[2], temp3[2];//p保存mid左右两边小于d的点集
  20.     if (high - low == 1)//两个点
  21.     {
  22.         //保存两个点
  23.         rec[0].x = s[low].x;
  24.         rec[0].y = s[low].y;
  25.         rec[1].x = s[high].x;
  26.         rec[1].y = s[high].y;
  27.         return Distance(rec[0], rec[1]);
  28.     }
  29.     if (high - low == 2)//三个点
  30.     {
  31.         d1 = Distance(s[low], s[low + 1]);
  32.         d2 = Distance(s[low + 1], s[high]);
  33.         d3 = Distance(s[low], s[high]);
  34.         if (d1 < d2&&d1 < d3)
  35.         {
  36.             rec[0].x = s[low].x;
  37.             rec[0].y = s[low].y;
  38.             rec[1].x = s[low + 1].x;
  39.             rec[1].y = s[low + 1].y;
  40.             return d1;
  41.         }
  42.         else if (d2 < d1&&d2 < d3)
  43.         {
  44.             rec[0].x = s[low+1].x;
  45.             rec[0].y = s[low+1].y;
  46.             rec[1].x = s[high].x;
  47.             rec[1].y = s[high].y;
  48.             return d2;
  49.         }
  50.         else if (d3 < d1&&d3 < d2)
  51.         {
  52.             rec[0].x = s[low].x;
  53.             rec[0].y = s[low].y;
  54.             rec[1].x = s[high].x;
  55.             rec[1].y = s[high].y;
  56.             return d3;
  57.         }
  58.     }
  59.     mid = (low + high) / 2;//取中间
  60.     d1 = ClosePoints(s, low, mid, rec);//左递归
  61.     temp1[0] = rec[0];//保存左边结果数组
  62.     temp1[1] = rec[1];
  63.     d2 = ClosePoints(s, mid + 1, high, rec);//右递归
  64.     temp2[0] = rec[0];//保存右边结果数组
  65.     temp2[1] = rec[1];
  66.     //找到最小的距离在左边还是在右边
  67.     if (d1 < d2)
  68.     {
  69.         d = d1;
  70.         rec[0] = temp1[0];
  71.         rec[1] = temp1[1];
  72.     }
  73.     else
  74.     {
  75.         d = d2;
  76.         rec[0] = temp2[0];
  77.         rec[1] = temp2[1];
  78.     }
  79.     index = 0;
  80.     //遍历mid的两边找到小于d的点集保存在p数组中
  81.     for (i = mid; (i >= low) && (s[mid].x - s[i].x) < d; i--)
  82.     {
  83.         p[index++] = s[i];
  84.     }
  85.     for (i = mid; (i <= high) && (s[i].x - s[mid].x) < d; i++)
  86.     {
  87.         p[index++] = s[i];
  88.     }
  89.     sort(p, p + index, cmp2);//按y排序
  90.     for (i = 0; i < index; i++)//遍历p数组中的点集
  91.     {
  92.         for (j = i + 1; j < i + 7 && j < index; j++)//遍历每个p[i]点的周围小于d的点(最多有7个点(能证明))
  93.         {
  94.             if ((p[j].y - p[i].y) > d)break;//大于d跳过
  95.             else
  96.             {
  97.                 d3 = Distance(p[i], p[j]);
  98.                 if (d3 < d)
  99.                 {
  100.                     rec[0].x = p[i].x;
  101.                     rec[0].y = p[i].y;
  102.                     rec[1].x = p[j].x;
  103.                     rec[1].y = p[j].y;
  104.                 }
  105.             }
  106.         }
  107.     }
  108.     return d;//返回最小距离
  109. }
  110. int main()
  111. {
  112.     Point p[MAXN];
  113.     int n;
  114.     cin >> n;
  115.     for (int i = 0; i < n; i++)
  116.     {
  117.         p[i].x = rand() % 100;
  118.         p[i].y = rand() % 100;
  119.         cout << "(" << p[i].x << "," << p[i].y << ") ";
  120.     }
  121.     sort(p, p + n, cmp2);//按x坐标排序
  122.     cout << endl;
  123.     for (int i = 0; i < n; i++)
  124.     {
  125.         cout << "(" << p[i].x << "," << p[i].y << ") ";
  126.     }
  127.     cout << endl;
  128.     Point rec[2];
  129.     int mindistance = ClosePoints(p, 0, n - 1, rec);
  130.     cout << "(" << rec[0].x << "," << rec[0].y << ") ";
  131.     cout << "(" << rec[1].x << "," << rec[1].y << ")";
  132.     cout << endl;
  133.     cout << mindistance << endl;
  134.     return 0;
  135. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值