最近的点对算法

Posted

技术标签:

【中文标题】最近的点对算法【英文标题】:Closest Pair of Points Algorithm 【发布时间】:2011-12-07 09:39:41 【问题描述】:

我目前正致力于在 C++ 中实现最接近的点对算法。也就是说,给定一个点列表 (x, y) 找到具有最小欧几里得距离的点对。我对此进行了研究,我对算法的理解如下(如果我错了,请纠正我):

从中间拆分点数组 递归地找到左右两半距离最小的点对。 按 y 坐标对左右两半进行排序,并将左侧的每个点与右侧的 6 个最近邻居(按 y 坐标)进行比较。这背后有一些理论上的东西,但这是我对需要做什么的理解。

我已经让算法的递归部分起作用,但我正在努力寻找一种有效的方法来为左侧的每个点找到右侧的 6 个最近邻居。换句话说,给定两个排序的数组,我需要为数组 A 中的每个点在数组 B 中找到 6 个最接近的数字。我假设这里需要类似于合并排序的东西,但还没有弄清楚。任何帮助将不胜感激。

【问题讨论】:

我的一位同事在Computational geometry 上向我展示了这些笔记。有趣的东西,可能对你有用。 我从CLRS 记得这个。一种分而治之的方法。是的,我记得 6 分(或者是 7 分),但我不记得细节了。无论如何,如果您可以访问这本书,那么解决方案就在那里。 【参考方案1】:

听起来你想要quad tree。

【讨论】:

我对该算法所做的研究都没有提到使用四叉树。 不过,这是一种组织二维点云的自然方式。如果你有这样一棵树,你可以通过包含它们的最小子树的级别来粗略地衡量两个点的接近程度:接近的点将出现在深子树下。这使您可以修剪需要检查以找到最接近的对的列表。【参考方案2】:

dist = min(dist_L, dist_R) 其中dist_L, dist_R 分别是在左右集合中找到的最小距离。

现在要找到一个点在左半边,另一个在右半边的最小距离,您只需要考虑 x 坐标在区间[x_m - dist, x_m+dist] 内的点。

现在的想法是考虑此区间内最近的 6 个点。因此,按每个点的 y 坐标对点进行排序,期待接下来的 6 个。这将导致 O(nlog^2(n)) 运行时间。

您可以通过加快排序过程将其进一步改进为O(nlogn)。为此,让每个递归调用也返回一个排序的点列表。然后要对整个列表进行排序,您只需合并两个已排序的列表。细心的读者会注意到这正是归并排序。

【讨论】:

谢谢,这正是我所需要的。我分别按 y 坐标对两个数组进行排序,并尝试将左侧数组中的点与右侧数组中最近的 6 个点进行比较,对此没有有效的方法。一切正常。 好吧,我仍然遇到的一个问题是如何在我的递归中实现合并排序。我的算法递归的基本情况是大小为 2 和 3 的子列表(据我所知,基本情况为 1 是没有意义的,因为点与自身之间的最小距离没有意义) .合并排序的递归部分的基本情况似乎是 1。那么我该如何组合这两种不同类型的递归呢? 对于长度为 2 或 3 的子列表,只需手动对列表进行排序。您不需要使用归并排序来执行此操作。 如何找到 y 坐标中最接近的六点?我只能想到二分查找,但这会花费 log n 时间,这也将导致 O(n log^2 n) 时间,即使在算法上搭载了归并排序。

以上是关于最近的点对算法的主要内容,如果未能解决你的问题,请参考以下文章

最近的点对算法

平面最近点对的算法实现

我可以计算距离严格小于 delta 的最近分割点对吗

找到两组矩阵之间最近的点对

最近对算法

平面最近点对问题