C++ 在二维点的两个数据集中寻找最近项的加速算法

C++ 在二维点的两个数据集中寻找最近项的加速算法,c++,algorithm,C++,Algorithm,嗨,我想改进这个非常慢的算法。它应该只返回一个点,该点是两个数据集中最近的两个点对中的一个 我使用的方法只是蛮力,很清楚地测试了每一组点之间的距离。一定有更好的办法 cv::Point FindClosesedValue(std::vector<cv::Point> & point_a, std::vector<cv::Point> point_b) { double lowest_distance = std::numeric_limits<doubl

嗨,我想改进这个非常慢的算法。它应该只返回一个点,该点是两个数据集中最近的两个点对中的一个

我使用的方法只是蛮力,很清楚地测试了每一组点之间的距离。一定有更好的办法

cv::Point FindClosesedValue(std::vector<cv::Point> & point_a, std::vector<cv::Point> point_b)
{
  double lowest_distance = std::numeric_limits<double>::max();
  cv::Point best_point;
  for (cv::Point & a : point_a)
  {
    for (cv::Point & b : point_b)
    {
      double distance = CvFunctions::DistanceSquared(b, a);
      if (distance < lowest_distance)
      {
        lowest_distance = distance;
        best_point = a;
      }
    }
  }

  return best_point;
}
cv::Point FindClosedValue(std::vector&Point_a,std::vector Point_b)
{
双最小距离=标准::数值限制::最大();
cv::点最佳点;
对于(cv::Point&a:Point_a)
{
对于(cv::Point&b:Point_b)
{
双距离=CVF函数::距离平方(b,a);
if(距离<最低距离)
{
最低距离=距离;
最佳点=a;
}
}
}
返回最佳_点;
}

请有人能告诉我正确的方法来加速这个代码,希望是以数量级的顺序。示例代码将是惊人的。

我曾经处理过一个类似的问题,我设法获得了100倍的加速,但这取决于数据

如果可以将一组点预排序为一个分幅网格,则可以利用分幅大小缩小需要测试的点的范围。给定点与特定平铺中的任何点都有最小和最大距离。您可以使用这些最小距离和最大距离来绑定要检查的瓷砖,从而避免检查远处瓷砖中的点

将点划分为平铺后,可以查找新点将属于哪个平铺,并从那里开始。根据您的数据,磁贴可能没有预先排序的点。最初,您只需要检查第一块瓷砖以及周围的瓷砖,直到找到任何一点。该点将给出最小距离的近似值。知道所选点与找到的点之间的最小距离后,可以继续检查平铺中的所有点,直到所选点与给定平铺中任何点之间的最小距离大于找到的最小距离。瓷砖中距离较远的任何点都不能比您已经找到的点更近。如果您发现新的较近点,则该最小距离当然会更新

排序步骤为O(n),查找步骤在n和n^2之间,因此预期时间最多应为O(n^2),如果有合适的点分布,可能更好,可能接近线性


至于tile大小,我发现选择tile时,每个tile中的点数大致等于覆盖数据集的tile数,从而产生最佳运行时。您可能可以使用层次化的分片做得更好,但我的解决方案从未如此复杂。

这是一个很好的问题。通常的递归显然行不通,因为两个点集可能聚集在空间的不同区域


不过,您仍然可以在
O(nlogn)
时间内解决这个问题。只需创建一个集合中所有点的kd树(k=2),并使用另一个集合中的所有点进行查询。

您阅读了吗?是的,这是一个数据集,而不是两个。这两个数据集有多大?您是多次搜索相同的数据集,还是每次执行搜索时都搜索不同的数据集?每个数据集大约为2000-4000。我需要用不同的数据集做很多工作。[OT]:引用可以是
const
,而
点缺少const ref\u b
。请解释一下为什么该方法不起作用?我看不出这里违反了什么先决条件。首先,如果递归的一侧根本没有双色对,那么它应该返回什么值?我知道了。经典算法适用于单个集合。不在两组之间。