在没有已知方程的图形中寻找最近点的高效算法

10

出于好奇心,我想问这个问题,因为我的简单实现似乎已经足够好了。然而,我很好奇一个更好的实现会是什么样子。

我有一组真实世界数据的图形。图表中没有重复的X值,并且在整个图形上X值以一致的速率递增,但是Y数据基于真实世界输出。我想编程地从任意给定点P找到图形上最近的点。我正在寻找一种高效(即快速)的算法来实现这一点。我不需要最精确的最近点,我可以接受一个“几乎”最近的点。

显然的懒惰解决方案是逐个遍历图中的每个点,计算距离,然后找到最小距离。但是,对于大型图表,理论上可能太慢了;对于我想要的东西来说太慢了。

由于我只需要一个近似的最近点,我想象中最理想的最快公式涉及生成最佳拟合线并使用该线实时计算点应该在哪里;但这听起来像是一个潜在的数学头疼,我不打算接受。

我的解决方案是一个hack,它仅在我假定我的点P不是任意的情况下起作用,即我假定P通常会靠近我的图形线,并且当发生这种情况时,我可以将远离X值从考虑中排除。我计算了与P共享X坐标的线上的点有多接近,并使用该点与P之间的距离来计算可能更接近点的最大/最小X值。

我不禁感到应该有比我的解决方案更快的算法(仅因为我假设99%的时间我的点P已经接近该线)。我尝试谷歌搜索更好的算法,但找到的算法中没有完全符合要求的算法,所以在所有不适当的算法混杂的情况下很难找到我要找的东西。所以,这里是否有人有建议的算法可以更有效地实现?请记住,由于我的需求已得到满足,我不需要完整的算法,只是好奇应该是什么样的正确解决方案。

3个回答

4
如果您将[x,y]点存储在quadtree中,则可以快速找到最近的点(类似于O(log n))。我认为这是在不对点的位置进行假设的情况下所能做到的最好的。与其在此处重复算法,不如看看link
您的解决方案非常好,通过检查点在y轴上的变化方式,您不能计算出需要检查的沿x轴的点数的边界,而不是使用任意一个。

我很遗憾地被卡在了一个点数组上,但对于我提出的通用问题,更好的数据结构可能是最佳解决方案。不过,您能详细说明一下您将如何使用四叉树吗? - drew
四叉树是一种通过递归分割空间的数据结构之一。查找附近(同一原子区域)点很容易,但查找最近的点则需要深度优先/广度优先/优先级排序搜索,稍微有些棘手。 - user180247

3
假设您的点为 P=(x,y),您的真实数据是一个函数 y=f(x)
步骤1:计算 r=|f(x)-y|
步骤2:在区间 I=(x-r,x+r) 中找到点。
步骤3:找到离点 P 最近的点在 I 中。

问题是计算f(x)。我该如何在不给我的代码增加大量复杂性的情况下解决这个问题? - drew
抱歉,f(x) 是你的“真实世界数据”。它是你在 x 处数据的 y 值。 - tskuzzy
对不起,我误读了你的回答。这与我的做法接近,只是我使用距离的平方作为我的 r 而不是 f(X) - y。也许我只是没有清晰地思考,但是似乎如果没有平方或平方根的话,这个方法不会奏效,因为距离是基于 X 和 Y 的平方。 (我现在的大脑功能不完全,所以我不能确定我只是没想明白呵呵) - drew
其实我刚意识到这会得到一个精确的答案,而不是近似值。画个图吧。画出你的函数曲线和一个点 P。现在画一个以 P 为圆心、半径为我的答案中定义的 r 的圆。任何在 I 外的点都无法被包含在这个圆内。 - tskuzzy

2
如果您能使用数据结构,一些常见的用于空间搜索(包括最近邻)的数据结构包括...
- 四叉树(以及八叉树等)。 - kd树 - bsp树(仅适用于静态点集)。 - r树
r树有许多变体。它与B+树非常相关,但是(取决于变体)在叶节点中的项目(点)上具有不同的排序。
Hilbert R树使用基于Hilbert曲线的点的严格排序。 Hilbert曲线(或者更准确地说是它的推广)非常适合对多维数据进行排序,以便空间中附近的点通常在线性排序中相邻。
原则上,Hilbert排序可以通过对点的简单数组进行排序来应用。这种自然聚类意味着搜索通常只需要搜索数组中的几个相当短的跨度-复杂之处在于您需要找出它们是哪些跨度。
我曾经有一个关于执行Hilbert曲线排序计算的好论文链接,但我已经失去了它。基于Gray码的排序会更简单,但在聚类效率上不如Hilbert曲线高效。实际上,Gray码和Hilbert曲线之间存在深刻的联系-我失去的那篇论文在很大程度上使用了与Gray码相关的函数。
编辑-我找到了那个链接-http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.133.7490

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接