Kd-Tree 插入顺序

Posted

技术标签:

【中文标题】Kd-Tree 插入顺序【英文标题】:Kd-Tree Insertion Order 【发布时间】:2021-10-10 23:29:25 【问题描述】:

我正在使用 KD-Tree 来优化对一组 2D 点 (x,y) 的范围搜索。 为了节省时间,我尝试使用 Java Topology Suite 的 KD-Tree。 但是,javadoc 声明:

请注意,KD-Tree 的结构取决于点的插入顺序。如果插入的点是连贯的(例如在一维或两个维度上单调),则树可能会变得不平衡。完美平衡的树只有 log2(N) 的深度,但不平衡的树可能更深。这对查询效率有严重影响

所以我的问题是:如何以最小化树高的方式将点插入 KD-tree

【问题讨论】:

【参考方案1】:

In 不会太担心。这有点像哈希映射,如果所有条目都必须发生相同的哈希码,则理论上它具有 O(n) 查找。实际上,除非哈希函数有问题,否则这种情况不太可能发生。

为避免不平衡,您应确保您的积分没有以任何方式排序。如果是,请考虑在插入之前对其进行洗牌。

另外,一些 kd-tree 实现有一个 rebalance() 函数,可以在插入(大部分)数据后调用。这将在内部重新平衡树。

最后,如果您真的想使用避免不平衡的特定插入顺序,您可以执行以下操作。请注意,这种方法不是最优的,它会避免最坏的情况,但通常不会产生完全平衡的树: 按 x 坐标对点进行排序,然后使用二分搜索插入它们。例如,如果您有 15 个点,则按“x”对它们进行排序以获得点 p0...p14 的排序列表。那么:

    取范围 (p7) 中的中间点并将其插入。 为分割点的每一边创建一个新范围:p0-p6 和 p8-p15 从 1) 重新开始,分别使用两个范围

这会产生以下插入顺序:

    回合:p7 圆形:p3 和 p11 圆形:p1、p5、p9、p13 圆形:p0、p2、p4、p6、p8、p10、p12、p14

为什么这不理想?

我们完全忽略了 y 坐标。这种方法只能避免 y 坐标的不平衡。 典型的 kd 树在 x 和 y 之间交替分裂。然而,我们不知道在给定的实现中哪个先出现,所以我们只能假设它总是在 x 上分裂。这不会立即造成伤害,但会妨碍更优化的插入。

【讨论】:

以上是关于Kd-Tree 插入顺序的主要内容,如果未能解决你的问题,请参考以下文章

[CQOI2016]K远点对(KD-Tree)

BZOJ 4066 kd-tree 矩形询问求和

BZOJ.2716.[Violet3]天使玩偶(KD-Tree)

BZOJ2626JZPFAR kd-tree+堆

bzoj2626JZPFAR KD-tree+堆

P3769 [CH弱省胡策R2]TATT [KD-Tree]