Algorithm 二维圆最近邻的最佳动态数据结构
题目是最主要的问题。我有一组圆,每个圆的中心C和半径r。两个圆之间的距离是它们中心之间的欧几里德距离减去半径。对于圆a和b d|ab=|C|a-C|b |-r|u a-r|b 注:如果圆圈重叠,则可能为负值 那么,在集合中查找给定圆的最近(最小距离)邻居的最快数据结构是什么 必须支持添加和删除带有以任意顺序交错的“查找最近的”查询的圆。事先对集合的几何分布一无所知 这将是一个系统的核心,在这个系统中,一个典型的圆圈数是50000个,需要10个成千上万的查询、插入和删除,理想的情况是在高端平板设备上以用户交互速度(一秒或更少)进行 最近邻点已经被研究得很透彻了,但是这个带有圆圈的版本似乎有点难 我已经研究了kd树、四叉树、r树以及这些树的一些变体。关于其中哪一个可能是最好尝试的建议,以及新的建议都会非常有帮助。是邻近结构的另一种可能性。它们不支持删除(?),但您可以在后台软删除和重建以防止垃圾堆积,这对于其他结构可能是一种有用的技术 从二维圆问题到三维点问题,有一个像这样的时髦度量。(您命名的邻近结构应该是可适应的。)将以(x,y)为中心、半径为r的圆映射到点(x,y,r)。将向量(dx,dy,dz)的长度定义为sqrt(dx**2+dy**2)+abs(dz)。这就产生了一个度量。要查找距离圆心(x,y)最近的圆(查询圆的半径不相关),请在(x,y,R)处进行近似搜索,其中R大于或等于圆的最大半径(可以修改近似结构,以便不必跟踪R)Algorithm 二维圆最近邻的最佳动态数据结构,algorithm,language-agnostic,computational-geometry,Algorithm,Language Agnostic,Computational Geometry,题目是最主要的问题。我有一组圆,每个圆的中心C和半径r。两个圆之间的距离是它们中心之间的欧几里德距离减去半径。对于圆a和b d|ab=|C|a-C|b |-r|u a-r|b 注:如果圆圈重叠,则可能为负值 那么,在集合中查找给定圆的最近(最小距离)邻居的最快数据结构是什么 必须支持添加和删除带有以任意顺序交错的“查找最近的”查询的圆。事先对集合的几何分布一无所知 这将是一个系统的核心,在这个系统中,一个典型的圆圈数是50000个,需要10个成千上万的查询、插入和删除,理想的情况是在高端平板设备
根据我在点上实现kd树和Voronoi图的经验,从头开始实现kd树将非常容易。即使你重复使用其他人强大的几何原语(如果你走这条路,请这样做,以保持你的理智),Voronoi/点位置的退化边情况也需要时间来纠正。如果可以保证圆没有大半径,至少是最大半径(R)比圆所在的区域小得多,比我认为的标准空间分割和最近邻搜索所能覆盖的区域小得多 在一个到给定圆的距离最小的集合中搜索圆时,给定圆的半径并不重要(距离定义)。因为只有圆心(点)与圆集合相比较,它是相同的 这样,只需在空间分区结构中存储三个中心(点集)就足够了。点的圆添加和删除是以标准方式进行的。可分两步找到距给定点最近的圆:
- 找到离给定点P最近的中心。用圆心C和半径r表示圆C
- 距离P较近的圆心只能位于P周围的环中,内半径r和外半径r-d(P,c)。搜索与该环相交的分区就足够了
通过结合这两个步骤可以优化搜索。在第一步中,已经访问了一些感兴趣的分区。通过存储访问的分区,并在这些分区中找到最小距离的圆圈,可以减少第二步中的搜索。我建议使用KD树或其他允许O(logn)最近邻的方法进行以下启发式搜索。而不是使用一个点和一个半径来表示一个圆。在圆本身上使用k个等距点,加上圆的中心,否则您可能会遇到大圆中的小圆的问题。这与使用k个顶点的正多边形表示圆的想法相同。然后,可以选取一个顶点并查找其最近的邻居(忽略同一圆上的顶点),以根据最近的正多边形找到最接近的圆的近似值 表演如下: 创建KD树:O(千牛日志千牛) 移除/添加KD树的圆圈:O(k对数kN) -在KD树中添加或删除圆的所有k点 最近圆查询(圆):O(k对数kN) -这是通过首先删除圆的所有k点(O(k log kN))来实现的,因为发现圆的最近邻点是圆本身并不十分有用。然后,对于圆中的每个k点,找到最近的邻居(O(k log kN))。一旦找到最近邻,实际最近邻(误差在一定范围内)就是距离最小的(基于点和半径计算真实距离后)(O(1)) 我建议使用k=log(N),如果您希望它快速,或者使用k=sqrt(N),如果您希望它准确
另外,我可能还没有考虑导致问题的一些特殊情况,所以请注意它们。感谢@David Eisenstatt提出的3d搜索结构的想法。这是最好答案的一部分,尽管不需要他奇怪的度量标准 关键是要详细了解最近邻搜索的工作原理。我会给四棵树看这个。k=3的Kd树是相似的。以下是伪代码:
# Let nearest_info be a record containing the current nearest neighbor (or nil
# if none yet) and the distance from point to that nearest neighbor.
def find_nearest_neighbor(node, target, nearest_info)
if node is leaf
update nearest_info using target and the points found in this leaf
else
for each subdivision S of node
if S contains any point P where dist(P,T) < nearest_info.distance,
find_neareast(S, target, nearest_info)
end
end
end
end
这里p是八叉树长方体的八分之一中的任意点。如何考虑长方体中的所有点?注意,对于给定的搜索,T的所有组件都是有效固定的,因此,如果我们将目标作为常量点写入(a、b、c),则更清晰:
这里我们省略了c=T.r
co
def dist(P,T)
return sqrt( (P.x - T.x)^2 + (P.y - T.y)^2 ) - P.r - T.r
end
def dist(P)
return sqrt( (P.x - a)^2 + (P.y - b)^2 ) - P.r
end