Algorithm 将点集分组到最近的点对
我需要以下问题的算法: 给我一组平面上的二维点p={(x_1,y_1),(x_2,y_2),…,(x_n,y_n)}。我需要按照以下方式将它们分组: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
将所有点放入(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)个查找时间。或者您可以只使用位集或数组或其他东西(因为您知道要处理多少个点),不需要摊销。太棒了。我需要查一下。