我想知道是否有一个算法用于计算最接近的位置(由纬度/经度表示)优于O(n)时间。
我知道我可以使用Haversine公式来获取从参考点到每个位置的距离并对ASC进行排序,但这对于大型数据集来说效率很低。
MySQL DISTANCE()函数如何执行?我在猜O(n)?
答案 0 :(得分:8)
如果您使用kd-tree来存储积分,则可以在O(log n)
时间(预期)或O(sqrt(n))
最差情况下执行此操作。
答案 1 :(得分:2)
比O(n)好吗?只有当你采用基数排序或存储位置时,才能使用代表它们所在位置的散列键。
例如,您可以将地球的纬度和经度划分为分钟,枚举结果区域,并为其所在区域制作哈希值。因此,当到达最近的位置时,您只需要检查最多9个哈希键 - 您可以事先测试相邻网格是否可能提供比目前为止找到的最佳位置更近的位置,从而减少位置集计算距离。它仍然是O(n),但具有小得多的常数因子。如果实施得当,你甚至都不会注意到它。
或者,如果数据在内存中或以其他方式随机访问,您可以按纬度和经度进行存储。然后,您可以使用二进制搜索在相应的数据集中查找最近的纬度和经度。接下来,您将继续阅读纬度或经度增加的位置(即前一个和后一个位置),直到找不到更近的位置为止。
你知道,当纬度分类数据任一侧的下一个位置的纬度不会比目前为止发现的最佳情况更接近时,你找不到一个近距离位置,即使它们属于同一经度计算距离的点。类似的测试适用于经度排序的数据。
这实际上比O(n)更好 - 更接近O(logN),我认为,但确实需要随机,而不是顺序访问数据,并重复所有数据(或数据的键,至少)。
答案 2 :(得分:2)
你提到MySql,但有一些非常复杂的spatial features in SQL Server 2008包括地理数据类型。有some information out there关于做你要问的事情的类型。我不太了解空间,足以谈论性能。但是我怀疑有一个有限的时间算法来做你想要的,但你可能能够对位置做一些快速设置操作。
答案 3 :(得分:2)
如果被搜索的数据集是静态的,例如美国所有加油站的坐标,则适当的索引(BSP)将允许有效搜索。自90年代中期以来,Postgres对二维索引数据提供了很好的支持,因此您可以进行此类查询。
答案 4 :(得分:2)
使用象限会大大缩短时间,尽管数学上无法确定复杂性(理论上所有点都可以位于单个象限中)。使用象限/网格的前提条件是,搜索点的最大距离。如果你只是寻找最近的点而没有给出最大距离,你就不能使用象限。
在这种情况下,请查看A Template for the Nearest Neighbor Problem (Larry Andrews at DDJ),其后验复杂度为O(log n)。我没有比较两种算法的运行时间。也许,如果你有一个合理的最大宽度,象限会更好。更好的通用算法是Larry Andrews的算法。
答案 5 :(得分:1)
如果您正在寻找(1)最近的位置,则无需进行排序。只需遍历列表,计算到每个点的距离并跟踪最近的点。当你通过列表时,你会得到答案。
更好的是引入网格的概念。您可以将每个点分配给网格。然后,对于搜索,首先确定您所在的网格,然后对网格中的点执行计算。你需要小心一点。如果测试位置靠近网格的边界,您还需要搜索这些网格。不过,这可能是高效的。
答案 6 :(得分:1)
我自己没有看过,但Postgres确实有一个专门用于管理GIS数据的模块。
在我前一生活中的应用中,我们获取了所有数据,计算了它是四叉树(用于2D空间)或八叉树(用于3D空间)的关键,并将其存储在数据库中。然后,从数据库加载值(以防止必须重新计算四叉树)并遵循标准四叉树搜索算法是一件简单的事情。
这当然意味着您将至少触摸一次所有数据,以使其进入数据结构。但是坚持这种数据结构意味着从那时起你可以获得更好的查找速度。我想你会为每个数据集做很多最近邻检查。
(对于kd-tree的维基百科有一个很好的解释:http://en.wikipedia.org/wiki/Kd-tree)
答案 7 :(得分:1)
您需要空间索引。幸运的是,MySQL在Spatial Extensions中提供了这样一个索引。他们在内部使用R-Tree索引 - 尽管它们的用途并不重要。上面引用的手册页有很多细节。
答案 8 :(得分:0)
我猜你理论上可以做到这一点,如果你有足够大的表来做这件事......其次,或许正确缓存可以让你获得非常好的平均情况?
答案 9 :(得分:0)
R-Tree索引可以用来加速这样的空间搜索。一旦创建,它允许这样的搜索优于O(n)。