重点:kd-tree 和 range tree

首先,可以参考 ass2 的第一题,kd-tree 的绘制和 range-tree 的绘制。

其次,我们来一点点深入了解这几个知识点。

# kd-tree

kd-tree 在后续的许多应用中都会有涉及。
首先,构建 kd-tree 需要 O (nlogn) 的构建时间和 O (n) 的构建空间 (具体推导过程可以去看 ppt)
🔹 方案一:使用排序方式找中位数
在每一层:

  1. 排序或选择中位点: O (n) 或 O (nlog⁡n),具体取决于用排序还是选择算法。
  2. 划分左右子树: O(n)
  3. 递归调用左右子树: 每边是 n/2 个点
    于是:
    T(n)=O(n)+2T(n/2)T(n) = O(n) + 2T(n/2)
    这就是典型的完全二叉树构建递归式,解出来是:
    T(n)=O(nlogn)T(n) = O(n \log n)
    以及标准的平衡二叉树空间复杂度 O (n)
    然后是查询的时间复杂度

查询时间分析核心思想
我们想知道:有多少个 “被访问但不产生结果” 的节点?(即这些节点的 region 与 R 相交,但最终不包含任何点)
老师采用的是可视化 + 递归建模来分析。


  • 假设我们用一条竖线 L 穿过查询矩形 R;
  • 然后问:有多少个 KD-Tree 划分出来的矩形 region 会跟这条 L 相交?
    结论:

这个数量最多是 O(n)O(\sqrt{n}),再乘上一个常数(最多 4 个区域被每个水平或垂直线段交到)。

定义 Q (n):查询一个 KD-Tree 有 nnn 个点时最多访问的节点数。

  1. 第一层我们访问 1 个节点;
  2. 第二层我们可能访问它的两个子树(假设是四个区域);
  3. 然后分别继续查各自的左右子树。
    于是得:
    Q(n)=1+2Q(n/2)Q(n)=O(n)Q(n) = 1 + 2Q(n/2) \quad \Rightarrow \quad Q(n) = O(\sqrt{n})

✅ 五、最终查询时间总结(第 6 张图)
你可以记住这句最核心的 KD-Tree 查询时间分析结论:
查询时间=O(n+k){查询时间} = O(\sqrt{n} + k)
其中:

  • n\sqrt{n}​:是最多访问这么多个 “无用节点” 的上界;
  • k:是最终在矩形 R 中找到的点的个数(输出代价)。

# range-tree

通俗来讲,就是把树按照 x 来排列,然后在每个子节点的上面挂一个子树,存放着 y 坐标
但是因此时间复杂度较高,因为两个树进行二分查找的时间复杂度都为 O (logn),因此,总的复杂度需要 O (logn) * O (logn) = O(log2n)O(log^2n)
那么有什么优化的方式吗?
Fractional Cascading
将 Range Tree 的子树部分切割成指针引导的结构,即可以 把子树的二分查找的优化掉。