Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 将点集分组到最近的点对_Algorithm_Computational Geometry_Nearest Neighbor - Fatal编程技术网

Algorithm 将点集分组到最近的点对

Algorithm 将点集分组到最近的点对,algorithm,computational-geometry,nearest-neighbor,Algorithm,Computational Geometry,Nearest Neighbor,我需要以下问题的算法: 给我一组平面上的二维点p={(x_1,y_1),(x_2,y_2),…,(x_n,y_n)}。我需要按照以下方式将它们分组: 在P中找到两个最近的点(x_a,y_a)和(x_b,y_b) 将该对添加到结果集R 从P 如果初始设置P不为空,则转至步骤1 对的返回集R 那个朴素的算法是O(n^3),使用更快的算法搜索最近邻,它可以改进为O(n^2 logn)。能做得更好吗 如果这些点不在欧几里德空间呢 示例(结果组用红色循环圈起来): 将所有点放入(timeO(n log(n

我需要以下问题的算法:

给我一组平面上的二维点p={(x_1,y_1),(x_2,y_2),…,(x_n,y_n)}。我需要按照以下方式将它们分组:

  • 在P中找到两个最近的点(x_a,y_a)和(x_b,y_b)
  • 将该对添加到结果集R
  • 从P
  • 如果初始设置P不为空,则转至步骤1
  • 对的返回集R
  • 那个朴素的算法是O(n^3),使用更快的算法搜索最近邻,它可以改进为O(n^2 logn)。能做得更好吗

    如果这些点不在欧几里德空间呢

    示例(结果组用红色循环圈起来):


    将所有点放入(time
    O(n log(n))
    )中,然后为每个点计算到其最近邻居的距离。将点和初始距离放入优先级队列。初始化一组空的已删除点和一组空对。然后执行以下伪代码:

    while priority_queue is not empty:
        (distance, point) = priority_queue.get();
        if point in removed_set:
            continue
        neighbor = rtree.find_nearest_neighbor(point)
        if distance < distance_between(point, neighbor):
            # The previous neighbor was removed, find the next.
            priority_queue.add((distance_between(point, neighbor), point)
        else:
            # This is the closest pair.
            found_pairs.add(point, neighbor)
            removed_set.add(point)
            removed_set.add(neighbor)
            rtree.remove(point)
            rtree.remove(neighbor)
    
    优先级队列不为空时:
    (距离,点)=优先级_queue.get();
    如果点位于已删除的集合中:
    持续
    邻居=树。查找最近的邻居(点)
    如果(点、相邻点)之间的距离<距离_:
    #前一个邻居已删除,请查找下一个邻居。
    优先级队列。添加((点、邻居、点之间的距离)
    其他:
    #这是最接近的一对。
    找到\u对。添加(点、邻居)
    已删除\u集。添加(点)
    已删除\u集。添加(邻居)
    删除(点)
    删除(邻居)
    

    最慢的部分是最近邻搜索。R-树不能保证这些最近邻搜索是
    O(log(n))
    。但它们往往是。此外,也不能保证每点执行
    O(1)
    邻居搜索。但通常是这样。所以平均性能应该是
    O(n log(n))
    (我可能缺少一个对数因子。)

    如果你的距离是任意的,你不能将你的点嵌入欧几里德空间(和/或空间的维数会非常高),然后基本上没有办法至少使用二次时间算法,因为在检查所有对之前,你不知道最近的对是什么。基本上,通过根据距离对所有对进行排序,然后维护一个布尔查找表,指示列表中的哪些点已经被取下,很容易接近这一点n、 然后按顺序浏览已排序对的列表,如果对中的两个点都不在已取点的查找表中,则将一对点添加到“最近邻居”中,如果是,则将对中的两个点添加到查找表中。复杂性O(n^2 log n),带O(n^2)额外的空间。

    我想这个问题需要一个动态Voronoi图

    当点集的Voronoi图已知时,可以在线性时间内找到最近邻对

    然后删除这两点可以在线性或次线性时间内完成(我没有找到关于这方面的精确信息)


    因此,在全球范围内,您可以期待一个O(N²)解决方案。

    您可以找到在O(nlogn)时间内运行的最接近的O(N^2 logn)对,您可以重复此操作N次,并且您将得到O(N^2 logn),这并不比您得到的更好

    不过,您可以利用分治算法的递归结构。考虑一下,如果您删除的一对点位于分区的右侧,那么左侧的所有内容都将表现相同,没有任何更改,因此您只需重新执行O(logn)合并步骤自下而上。但是考虑到第一个新合并步骤将是合并2个元素,第二个合并4个元素,然后8个,然后16个,…,n/4,n/2,n,因此这些合并步骤的操作总数是O(n),因此在O(n)中得到第二个最接近的对。因此,通过删除之前找到的对,您可以重复这个n/2次,并获得一个总的O(n^2)运行时,其中包含O(nlogn)额外的空间,以跟踪递归步骤,这样会更好一些


    但你可以做得更好,有一个随机数据结构,可以让你在你的点集中进行更新,并得到一个预期的O(logn)查询和更新时间。我不太熟悉这个特定的数据结构,但你可以在中找到它。这将使你的算法O(nlogn)预计时间,我不确定是否有具有类似运行时的确定性版本,但这些版本往往更麻烦。

    您能否详细说明输出的具体内容,例如,您能否给出一个输入输出示例?
    PriorityQueue
    ?@sircodesalot您能详细说明一下吗?实际上,它仍然是N^2 log N,但您基本上可以将所有距离转储到优先级队列中,然后读取最近的对。使用
    Set
    跟踪看到的项目。
    Set
    有O(1)个查找时间。或者您可以只使用位集或数组或其他东西(因为您知道要处理多少个点),不需要摊销。太棒了。我需要查一下。