加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

algorithm – Scala中的高效最近邻搜索

发布时间:2020-12-16 19:17:53 所属栏目:安全 来源:网络整理
导读:让这个坐标与欧几里德距离, case class coord(x: Double,y: Double) { def dist(c: coord) = Math.sqrt( Math.pow(x-c.x,2) + Math.pow(y-c.y,2) ) } 然后让一个坐标网格 val grid = (1 to 25).map {_ = coord(Math.random*5,Math.random*5) } 然后对于任何
让这个坐标与欧几里德距离,

case class coord(x: Double,y: Double) {
  def dist(c: coord) = Math.sqrt( Math.pow(x-c.x,2) + Math.pow(y-c.y,2) ) 
}

然后让一个坐标网格

val grid = (1 to 25).map {_ => coord(Math.random*5,Math.random*5) }

然后对于任何给定的坐标

val x = coord(Math.random*5,Math.random*5)

最接近x的点是

val nearest = grid.sortWith( (p,q) => p.dist(x) < q.dist(x) )

所以前三个最近的是nearest.take(3).

有没有办法让这些计算更具时间效率,特别是对于有一百万点的网格的情况?

解决方法

我不确定这是否有用(甚至是愚蠢的),但我想到了这个:

您使用排序函数对网格中的所有元素进行排序,然后选择前k个元素.如果你考虑像递归合并排序这样的排序算法,你有这样的事情:

>拆分一半
>两个部分递归
>合并两个分类的一半

也许你可以根据自己的需要优化这样的功能.合并部分通常合并来自两半的所有元素,但您只对合并产生的第一个k感兴趣.所以你只能合并,直到你有k个元素并忽略其余元素.

所以在最坏的情况下,k> = n(n是网格的大小),你仍然只有merge-sort的复杂性. O(n log n)老实说,我无法确定此解决方案相对于k的复杂程度. (此刻太累了)

以下是该解决方案的示例实现(它绝对不是最佳的而不是一般化的):

def minK(seq: IndexedSeq[coord],x: coord,k: Int) = {

  val dist = (c: coord) => c.dist(x)

  def sort(seq: IndexedSeq[coord]): IndexedSeq[coord] = seq.size match {
    case 0 | 1 => seq
    case size => {
      val (left,right) = seq.splitAt(size / 2)
      merge(sort(left),sort(right))
    }
  }

  def merge(left: IndexedSeq[coord],right: IndexedSeq[coord]) = {

    val leftF = left.lift
    val rightF = right.lift

    val builder = IndexedSeq.newBuilder[coord]

    @tailrec
    def loop(leftIndex: Int = 0,rightIndex: Int = 0): Unit = {
      if (leftIndex + rightIndex < k) {
        (leftF(leftIndex),rightF(rightIndex)) match {
          case (Some(leftCoord),Some(rightCoord)) => {
            if (dist(leftCoord) < dist(rightCoord)) {
              builder += leftCoord
              loop(leftIndex + 1,rightIndex)
            } else {
              builder += rightCoord
              loop(leftIndex,rightIndex + 1)
            }
          }
          case (Some(leftCoord),None) => {
            builder += leftCoord
            loop(leftIndex + 1,rightIndex)
          }
          case (None,Some(rightCoord)) => {
            builder += rightCoord
            loop(leftIndex,rightIndex + 1)
          }
          case _ =>
        }
      }
    }

    loop()

    builder.result
  }

  sort(seq)
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读