数据结构相关笔记③
W4
二叉搜索树(Binary Search Tree)
-
定义:二叉搜索树(Binary Search Tree,BST)是一种二叉树,存储键或键值对,满足以下性质:
- 对于每个节点 v,其左子树中的所有节点的键值都小于 v 的键值。
- 其右子树中的所有节点的键值都大于 v 的键值。
- 中序遍历 (Inorder Traversal) 二叉搜索树将会以递增顺序访问键值。
-
特点:任意节点 v 的左子树节点值均小于 v,右子树节点值均大于 v。搜索、插入、删除操作的时间复杂度与树的高度相关。
二叉搜索树的操作
1. 搜索(Search)
从根节点开始,沿着树向下遍历,依次比较要查找的键 k 与当前节点的键值:
- 如果 k 小于当前节点的键值,继续递归搜索左子树。
- 如果 k 大于当前节点的键值,继续递归搜索右子树。
- 如果找到外部节点(空节点),则说明树中没有该键。
def search(k, v): |
2. 插入(Insertion)
首先按照搜索的方式找到适合插入的外部节点 w。替换该外部节点,创建一个新的内部节点以存储键值。
def insert(k, v): |
3. 删除(Deletion)
需要先找到要删除的节点 w。删除分为两种情况:
- 情况1: 如果 w 有一个外部子节点,直接移除该节点并提升另一个子节点的位置。
- 情况2: 如果 w 有两个内部子节点,需要找到后继节点(右子树中键值最小的节点),替换内容并移除该后继节点。
def remove(k): |
二叉搜索树的时间复杂度
二叉搜索树的操作时间复杂度与树的高度 h 成正比:
- 最坏情况: 当树退化成链表时,树的高度为 n,时间复杂度为 O(n)。
- 最好情况: 树是平衡的,高度为 O(logn),操作的时间复杂度为 O(logn)。
因此,二叉搜索树在平衡的情况下,搜索、插入和删除操作都可以在 O(logn) 时间内完成,但在最坏情况下可能退化为 O(n)。
区间查询(Range Query)
区间查询的目的是在二叉搜索树中找到所有键值在给定区间 [k1, k2] 之间的节点,并将它们按顺序输出。通常,区间查询涉及遍历树的某些部分,并跳过那些不可能包含目标值的分支,以减少遍历的工作量。
区间查询的工作原理
由于二叉搜索树的结构特性(左子树节点的键值小于根节点,右子树节点的键值大于根节点),我们可以通过以下方法来高效地查找范围内的所有节点。
-
基本思想
- 当当前节点的键值小于 k1 时,意味着该节点和它的左子树中的所有节点的键值都小于 k1,因此我们可以忽略左子树,直接继续在右子树中查找。
- 当当前节点的键值大于 k2 时,意味着该节点和它的右子树中的所有节点的键值都大于 k2,因此我们可以忽略右子树,直接在左子树中查找。
- 如果当前节点的键值在 [k1, k2] 范围内,那么这个节点就是一个有效节点,我们可以将其输出,并继续递归地在它的左右子树中查找。
-
区间查询的伪代码
def range_query(node, k1, k2, result): |
- 时间复杂度分析
- 最优情况下(即树是平衡的,且区间较小),只需遍历树的一部分,时间复杂度为 O(logn + k),其中 n 是树中的节点数,k 是返回的符合条件的节点数量。
- 最坏情况下(例如,树退化为链表或区间很大),需要遍历树的每个节点,时间复杂度为 O(n)。
AVL 树 (Adelson-Velsky and Landis Tree)
AVL树是一种自平衡二叉搜索树,通过严格控制树的高度来确保高效的查找、插入和删除操作。它以两位发明者Adelson-Velsky和Landis的名字命名。下面是AVL树的详细介绍:
1. AVL树的定义
-
二叉搜索树 (BST) 特性:
- 左子树中所有节点的值都小于当前节点的值。
- 右子树中所有节点的值都大于当前节点的值。
-
平衡因子 (Balance Factor):
- 对于任意一个节点,平衡因子定义为该节点的左子树高度与右子树高度的差值:
- 平衡因子 = 左子树的高度 - 右子树的高度
- 一个AVL树的每个节点的平衡因子必须是 -1、0 或 1。如果某个节点的平衡因子不在此范围内,树就不再平衡,需要通过旋转操作恢复平衡。
2. AVL树的操作
插入操作 (Insertion)
AVL树的插入操作和普通的二叉搜索树相同,但插入后可能导致某些节点的平衡因子超出范围,因此需要进行旋转操作来重新平衡树。
- 步骤:
- 按照二叉搜索树的规则插入新节点。
- 从插入节点开始向上回溯,更新每个祖先节点的平衡因子。
- 一旦某个祖先节点的平衡因子超出范围(即平衡因子不是 -1、0、1),需要对该节点进行旋转操作。
旋转操作 (Rotations)
AVL树的关键在于通过旋转来恢复平衡。有四种旋转操作:
-
单右旋转 (Right Rotation, RR):
- 发生在左子树高度超过右子树时。
- 通过旋转将右子树的高度提升,恢复平衡。
-
单左旋转 (Left Rotation, LL):
- 发生在右子树高度超过左子树时。
- 通过旋转将左子树的高度提升,恢复平衡。
-
左-右旋转 (Left-Right Rotation, LR):
- 先对左子树进行左旋转,然后再对根节点进行右旋转。
-
右-左旋转 (Right-Left Rotation, RL):
- 先对右子树进行右旋转,然后再对根节点进行左旋转。
删除操作 (Deletion)
AVL树的删除操作和普通的二叉搜索树相同,但删除后也可能导致树失衡,因此需要进行旋转来重新平衡树。
- 步骤:
- 按照二叉搜索树的规则找到要删除的节点并删除它。
- 从删除节点的父节点开始,向上回溯,更新每个祖先节点的平衡因子。
- 一旦某个祖先节点的平衡因子超出范围,进行旋转操作恢复平衡。
3. 时间复杂度
由于AVL树是严格平衡的,树的高度最多为 O(logn),因此各种操作(如查找、插入和删除)的时间复杂度都是 O(logn)。