【问题标题】:K-D Tree vs R-Tree for small, dynamic data用于小型动态数据的 K-D 树与 R-Tree
【发布时间】:2014-02-24 23:10:56
【问题描述】:

我已经阅读了几篇关于 K-D 树与 R-Tree 的 SO 帖子,但我仍然对我的具体应用有一些疑问。

对于我的 Java 应用程序,我想维护相对少量的空间数据点(几十万)。关键是数据插入不会被批量加载,而是频繁且增量地插入。我还应该提到,我将对空间域的子区域执行大量的周期性范围查询。

我读到 K-D 树通常不支持增量构建,而 R-树更适合于此,因为它们保持平衡状态。

但是,在查看此处建议的解决方案后: Java commercial-friendly R-tree implementation?

我没有发现这些实现很容易用于返回范围搜索中的点列表。但是,我发现:http://java-ml.sourceforge.net/ 有一个非常好的 K-D 树实现,它可以快速运行,并且在一组测试点 (~25K) 上优于标准数组存储。此外,我读过 R-trees 在处理点时会存储冗余信息(因为点是一个最小 = 最大值的矩形)。

由于我使用的点数较少,这两种结构之间的差异是否比使用存储数百万点的数据库应用程序更重要?

【问题讨论】:

    标签: java kdtree r-tree


    【解决方案1】:

    R-trees 不能存储点是不正确的。它们旨在支持矩形,并且需要在内部节点处这样做。但是一个好的实现应该在叶级存储点,并且在那里大约有双倍的数据容量。

    您可以简单地存储点,并将它们公开为具有 min=max 的“矩形”到树管理代码。

    您的数据不小。小就像 100 个物体。对于 100 个对象,R-tree 没有多大意义,因为它可能只包含一个叶子。为了获得良好的性能,R-tree 需要良好的扇出。 k-d-tree 的扇出总是 2;它们是二叉树。在 100k 个对象时,k-d-tree 将非常深。假设您有 100 个扇出(对于动态 r-tree,那么您应该允许每页最多 200 个对象),您可以在 3 级树中存储 100 万个点。

    我使用了ELKI R*-tree,它真的很快。但它对商业并不友好,除非您获得不同的许可:它是 AGPL-3 许可的,这是一个 copyleft 许可。

    此外,API 不是为独立使用而设计的。如果你想使用它们,最好的方法是使用完整的 ELKI 框架,而不是试图撕掉 R*-tree。

    如果您的数据是低维数据(例如 3 维)并且有一个有限的界限,请不要低估简单的基于网格的方法的性能。特别是对于内存操作。在许多情况下,我什至不会使用八叉树,而只是为我的用例定义最佳网格,然后使用对象列表来实现它。在每个网格单元内保持一个坐标排序,以进一步提高性能。

    【讨论】:

    • 我的区域的边界不是先验的,并且会随着插入的数据而改变。如果必须适应可用网格的增长,您认为基于网格的方法是否值得研究?
    • 只要您对边界有所了解,网格方法仍然可以很好地工作,如果您将网格设计为可以向任何方向增长(例如,通过允许负索引,并且只存储占用的网格细胞)。
    • 可以使用哪些简单的基于网格的方法?
    • 取决于您的数据。在每个维度上尝试 10-100 个网格箱。在点网格箱内线性扫描,然后是相邻网格箱,直到您可以完全修剪它们。
    【解决方案2】:

    如果您想频繁添加/删除/更新数据点,您可能需要查看 PH-Tree。开源 Java 版本可用:www.phtree.org

    它有点像四叉树,但通过使用二元超立方体和前缀共享更有效。

    它具有出色的更新性能(无需重新平衡)并且内存效率很高。它适用于较大的数据集,但 100K 应该适合 2 或 3 维。

    【讨论】:

      猜你喜欢
      • 2016-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-12
      相关资源
      最近更新 更多