【问题标题】:Best algorithm for comparing a base coordinate to a list of n coordinates and determining the closest m coordinates?将基本坐标与 n 坐标列表进行比较并确定最接近的 m 坐标的最佳算法?
【发布时间】:2010-10-31 18:39:08
【问题描述】:

我现在有一些代码在做这个。它适用于中小型列表,但是当我有一个大小为 n > 5000 的列表时,我的算法在移动设备上可能需要将近 1 分钟才能运行。我基本上是将 Java 中的 Coordinate 对象与 Coordinate 对象的列表(向量)进行比较。

这是我的基本算法:

  • 遍历列表nx中的每个元素
  • 如果“10 个最接近”列表中的项目少于 10 个,则将 nx 添加到列表中 并转到下一个元素
  • 如果“10 最接近”列表已经有 10 个项目,则计算 nx 与底座之间的距离 坐标
  • 如果距离小于“10 个最近距离”中的最远距离 列表”,然后删除最远的项目 从该列表中并用 nx 替换它

我一直在关注这一点,并试图找到一种更有效的方法。这有点像排序算法问题,所以一定有更好的方法。

这是我的距离计算方法:

public static double distance(double lat1, double lon1, double lat2, double lon2, char unit) {

  double theta = lon1 - lon2;

  double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));

  dist = acos(dist);

  dist = rad2deg(dist);

  dist = dist * 60 * 1.1515;

  if (unit == 'K') {

    dist = dist * 1.609344;

  } else if (unit == 'N') {

    dist = dist * 0.8684;

    }

  return (dist);

}

【问题讨论】:

  • 您如何比较距离,如果您计算实际距离,请告诉我们如何。这里的一些简化(比如避免计算平方根)可以为您节省大量的执行时间。下一步可能是使用优先级队列而不是 10 个元素的向量,但 10 是一个很小的数字,所以队列的优势可能很小
  • @Steve C - 如果您的算法实现正确,即使 N = 100000,它也应该可以快速运行。
  • 您有使用Vector 的特定理由吗?最好使用ArrayList
  • @Petar Minchev 请注意,这是在嵌入式设备上,它可能比 PC 慢得多。
  • @starblue 我错过了,谢谢:) 我发布的答案只是原则上。如果NlogN 不适合他,他当然必须使用其他算法。

标签: java algorithm math gps coordinates


【解决方案1】:

您可以将坐标存储在一些space partitioning tree 中。

或者,对于更简单的方法,您可以使用二维桶数组,并首先检查最近的桶,直到找到足够多的最近邻居。这只有在坐标分布均匀的情况下才有效。

编辑:要比较距离,您可以预先计算球体上的 3D 坐标并在比较中使用欧几里得距离的平方:

dx * dx + dy * dy + dz * dz

【讨论】:

  • 这是我的距离计算算法。它非常精确,但我认为仅计算列表中最接近的 10 个时我可能不需要那种精确度:
  • public static double distance(double lat1, double lon1, double lat2, double lon2, char unit) { double theta = lon1 - lon2;双距离 = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta )); dist = acos(dist); dist = rad2deg(dist);距离 = 距离 * 60 * 1.1515; if (unit == 'K') { dist = dist * 1.609344; } else if (unit == 'N') { dist = dist * 0.8684; } 返回(分布); }
  • 天哪,可怜的嵌入式设备。你绝对应该考虑简化它。并更好地将其编辑到问题中,使其更具可读性。
【解决方案2】:

好吧,也许用数组来做这件事会更快。您可以比较距离的平方而不是距离,这意味着您不必使用平方根。

最好有实际的代码。

【讨论】:

    【解决方案3】:

    您也许可以使用类似website 的方法来限制实际需要您计算距离的点数。

    该网站展示了如何计算一个点和给定距离的纬度、经度边界坐标。这与您遇到的问题不完全相同,但它可以用作过滤器。在您的情况下,您显然是在尝试找到距给定点最近的 10 个(或 n 个)点。您可以应用以下算法来查找 10(或 n)个最近点:

    对于前 n 个点,您可以通过完整的距离 计算,保存沿每个点的距离。

    保存整体最长距离。计算纬度、经度边界 框如上面的网站所示。

    继续完成其余的点。

    如果任何点在纬度、经度边界框之外,则不能 比当前 10 个最近点中的任何一个都更近。如果在里面 边界框,计算距离。

    丢弃前一组 10 个“最近”点中最远的一个。

    根据新的最远点重新计算纬度、经度边界框。

    重复直到处理完所有点。

    这种方法的好处是您可以避免对大量点进行繁重的计算。根据您的点的分布,您仍然可能会遇到性能不佳的问题,例如,如果这些点是有序的,使得它们与您的目标点的距离越来越小(point[0] 是最远的,而 point[N]是最接近的))。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-17
      相关资源
      最近更新 更多