【Algorithms公开课学习笔记10】 符号表part3——平衡搜索树的应用

本文探讨了平衡搜索树(如kd树)在几何问题中的应用,包括一维范围搜索、线段相交、二维正交范围查找和区间搜索树。通过这些数据结构,可以高效解决线段相交、矩形相交等问题,实现时间复杂度优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Geometric Application of BSTs 平衡搜索树的几何应用

0. 前言

在前面的文章中,我们分析了符号表的许多基本操作,包括:查找、插入、删除等。现在我们新增两个操作:范围查找(range search)范围统计(range count)。这两个操作中数据的SQL查询语句很常见。

1. 一维范围搜索

基本概念

一维查找的几何解释如下:(结合下图)

  • key是作为一维线段上的点
  • 查找/统计包含在一维区间上的点(一维区间最大就是一维线段)

这就是范围查找和范围统计的应用范围,因此,符号表可以用来实现一维查找。

基本操作

在前面的文章中也分析过,通过无序链表和有序数组来实现符号表存在性能问题,而通过二叉搜索树(BST)来实现才能满足 ~lgN的性能要求。

  • 无序链表:插入很快,但查找需要遍历链表
  • 有序数组:由于插入需要确定次序导致很慢,但查找可以使用二分法使得性能达到lgN

因此,我们将采用BST来实现一维查找。

一维统计

//统计lo和hi之间的节点个数
public int size(Key lo, Key hi){
    //rank返每个节点的有序序列的排位
    if (contains(hi)) return rank(hi) - rank(lo) + 1;
    else return rank(hi) - rank(lo);
}

性能:查找到lo的路径+查找到hi的路径 ~lgN。

一维查找

一维查找是查找在lo和hi之间的所有所有节点。

  • 递归地查找左子树的所有key
  • 查找当前节点的的key
  • 递归地查找右子树的所有key(保存满足条件的key)

性能:查找到lo的路径+查找到hi的路径+匹配的节点数 ~lgN+R (R就是匹配的节点数)

2. 线段相交

线段相交就是在一个二维平面内,查找所有相交的线段。传统的方法就是两两对比,确定是否相交,但这种方法需要平方级的时间要求。下面介绍一个高性能的方法。

扫描法

扫描法的基本原理:在二维平面内,用一条垂直的线从左到右进行扫描。x坐标作为触发事件,事件如下:

  • 对水平的线段,当遇到线段的左端点时,将y坐标插入二叉搜索树中
  • 对水平的线段,当遇到线段的右端点时,将y坐标从二叉搜索树中删除
  • 对垂直的线段,当遇到端点时,将线段的上下端点作为查找范围,进行二叉搜索树的范围查找,查找的结果就是与该线段相交的其他线段(结合下图)

通过扫描法,就可以将二维的线段相交的问题转换成一维查找的问题。在N条线段存在R个相交点的场景下,时间性能表现为 ~NlgN+R

3. kd树

分析kd树首先要明白二维正交范围查找(2-d orthogonal range search)的背景和基本概念。

二维正交范围查找

二维正交范围查找的几何解释为:(结合下图)

  • 可以作为二维平面空间上的点
  • 查找/统计包含在二维矩形内的点(二维矩形在二维平面空间内)

网格实现法

网格实现法是二维正交范围查找的最佳实现方法,网格实现法的描述如下:(结合下图)

  • 将二维平面空间分割成 M*M 个网格
  • 对每一个网格都创建一个列表,来存在落在该网格的节点
  • 使用二维数组来直接索引相关的网格方块
  • 插入:根据新节点的坐标索引到网关,再插入到网格对应的列表
  • 范围查找:只查找与二维矩形相重叠的网关方块对应的节点列表即可

空间性能:M*M+N(M表示网格,N表示节点)
时间性能:平均每个网格的查找时间为 1+ N/M^2

因此,对M的选取是非常关键的。M太大网格就会小,导致浪费空间;M太小网格就会大,导致太多节点挤在同一个网格。理论上,最佳为M = √N。

kd树

在网格实现法中,存在一个不可忽视的问题——节点聚簇。当节点聚簇的时候,像上述那样均分网格就会导致节点挤在一小部分网格中(最终导致该网格对应的列表过长)。此时,需要一种合理地切分网格的方法,就是接下来要重点分析的kd树法。

kd树法就是递归地将空间分成两部分。与BST不同的是,kd树需要交替地使用x坐标和y坐标作为key。使用x坐标为key时就垂直切分,使用y坐标作为key时就水平切分。

范围查找

  • 检查节点是否在矩形内
  • 根据矩形的位置,判断往哪个方位继续查找

在下图中,节点1不在矩形内,根据位置需要查找左子节点3,忽略右子树全部节点。接着发现矩形横跨了节点3的分割线,所以节点3的左右节点均要查找。以此类推。

时间性能:平均情况下是R+lgN,最坏情况下是R+√N

最邻近节点

查找与查询节点最近的节点

  • 计算节点与待查节点的距离l
  • 分别计算左右子节点与待查节点的距离,如果出现小于l的则往该子节点路径走(有可能左右子节点都符合条件),如果大于l的就忽略

时间性能:平均情况下是lgN,最坏情况时N

kd树也可以推广到三维立体空间中,本文不作详述。

4. 区间搜索树interval search trees

基本概念

在一维区间查找中,有一个很重要的操作就是一维区间相交查询:给定一个区间(lo, hi),查找出于该区间相交的其他区间。(结合下图)

所谓的区间查找树,就是树的每一个节点存的是一个区间:(结合下图)

  • 使用左端点作为节点的key(故比较对象是左端点)
  • 每一个节点要存储以其为根的子树中的最大key值(包括节点本身)

基本操作

插入

以插入(lo, hi)为例

  • 左端点lo作为key值,比较key值后确定其位置,然后插入
  • 更新每一个节点所保存的最大key值

查找

查找是指查找出与给定节点相交的其他节点,以查找节点(lo, hi)为例

  • 如果节点相交,则返回
  • 如果左子树为空,往右边走
  • 如果左子树最大key值小于lo,往右边走
  • 其他情况往左边走
//根节点
Node x = root;
while (x != null){
    if (x.interval.intersects(lo, hi)) return x.interval;//存在相交,返回
    else if (x.left == null) x = x.right;//如果左子树为空
    else if (x.left.max < lo) x = x.right;//如果左子树最大key值小于lo
    else x = x.left;
}
return null

这么比较是因为有以下特殊情况:

  • 如果往右边走,则表示一定不会在左边相交
  • 如果往左边走,仍有可能会在右边相交,或者两边都不相交

为了保证时间性能,可以采用红黑树来实现区间搜索树,这样就可以将时间性能保持在 ~lgN的水平,本文不作详述。

5. 矩形相交

矩形相交是在一个二维平面内,查找所有相交的矩形。传统的方法就是两两对比,确定是否相交。但这种做法需要平方级的时间要求,因此,使用扫描法可以保证时间性能。

在二维平面内使用一条垂直的线段从左到右扫描,矩形的x坐标触发事件,事件包括:(结合下图)

  • 当遇到矩形的左边界时,将y坐标区间插入区间搜索树中;在插入之前,先对待插入的坐标区间做区间查找,以确定相交情况。
  • 当遇到矩形的由边界时,将y坐标区间从区间搜索树中删除

通过扫描法,就可以将二维的矩形相交的问题转换成区间查找的问题。在N条线段存在R个相交点的场景下,时间性能表现为 ~NlogN+RlogN

小结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值