【问题标题】:Optimize the search of the closest bus stop优化搜索最近的公交车站
【发布时间】:2017-11-06 23:58:19
【问题描述】:

我想知道是否有更好的方法,给定一个纬度和一个经度,找到最近的公共汽车站,而不是通过完整的 ArrayList:

这就是 BusStation 类:

    while(iteratore.hasNext()){    // for the full array size...
        tmp = (BusStation) iteratore.next();
        tmpDistance = getDistance(currentLat, currentLong, tmp.getStopLat(), tmp.getStopLon());
        if(tmpDistance < nearestDistance){  // if the distance is smaller ...
            nearestStop = tmp;  // i save the bus stop
            nearestDistance = tmpDistance;  // i save the distance too
        }
    }

这是效率不高的代码,它工作,但每次调用该方法时都必须查看具有 n 复数的完整数组。

我们如何通过 数据结构 作为 二叉搜索树 来优化它?

方法的签名应该是这样的:

public BusStation search(double currentLat, double currentLong){}

【问题讨论】:

  • 可以使用Haversine公式
  • 到目前为止,您自己尝试过哪些优化?
  • 您可以对ArrayList 进行排序,然后将其与您的值进行比较。一旦你找到了最佳距离,你就可以休息了。这会将您的复杂性从 O(n^2) 更改为 O(n log n)
  • @Nehorai Haversine 公式没有帮助。它为您提供球体上坐标之间的距离。但不能帮助您有效地找到最小的。
  • 也许这个问题的答案中的一种方法可以帮助stackoverflow.com/questions/1901139/… 另外,您可以添加您的getDistance() 方法实现,因为它很可能会在搜索优化中发挥作用。

标签: java optimization data-structures binary-search-tree latitude-longitude


【解决方案1】:

您的核心算法已尽您所能。但是,您可以通过首先根据位置将它们分类到存储桶中来减少必须检查的项目数量。例如,您可以为每 1 平方公里的地图设置一个存储桶。

如果您知道地图上的每个点在 1 公里范围内都有一个公交车站,那么您只需搜索目标 1 公里广场内的站点及其 8 个邻居——因为围绕地图上的任何点绘制了一个半径为 1 公里的圆圈中心方格将完全包含在这 9 个方格中。

在许多实际情况下,根据您对止损点分布的了解,您可能会想出一种廉价的方法来选择一小部分保证包含您正在寻找的止损点的方格。它可能非常简单(“地图上的任何地方距离停靠点都不超过 1 公里,因此坐标周围的 3x3 方格将包含一个”)或更多技术性(“在城市中心,3x3 搜索保证命中;在郊区我需要 5x5")

如果算法需要更通用,那么您可以从搜索这 9 个正方形开始,然后添加与越来越大的圆圈重叠的正方形。

radius = 1
while(true) {
    Set<Square> squares = difference(
         squaresContainedIn(radius), 
         squaresContainedIn(radius - 1));
    busStop = findNearest(coords, squares);
    if(busStop != null) {
        return busStop;
    }
    radius ++;
}

不过要小心;你必须稍微改进一下这个算法。最接近的项目有可能在两个方格之外,即使有一个候选人在一个方格之外:

a 33333
b 32223
c 32123
d 32223
e 33333

  ABCDE

即使在B,d(第一个“搜索带”)的远角有一个项目,笛卡尔距离最近的停靠点也可能在E,c(第二个“搜索带”)中。有多种方法可以让算法处理这个问题:

  1. 检查带时,忽略不在当前半径范围内停止。在考虑radius 的下一次迭代时,您将需要再次查看这些方块。
  2. 或者,当您找到候选人时,在您搜索下一个乐队之前不要将其视为“最终”项目。

或者,根据实际要求,您可能会认为偶尔出现错误(但仍然有用)的答案是可以接受的速度折衷。

如果您想扩大这种方法,您可以使用QuadTree 结构,其中方块嵌套在较大的方块中。

【讨论】:

猜你喜欢
  • 2018-01-06
  • 2021-10-21
  • 2018-10-23
  • 1970-01-01
  • 2013-08-31
  • 2011-02-22
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
相关资源
最近更新 更多