第七讲与第八讲 Binary Search Trees

满二叉树:所有结点的孩子数均为0或者2

完美二叉树:非叶子结点均有2个孩子,且所有叶子姐点深度相同


二叉搜索树(Binary Search Trees)

元素查找(参考数据结构)

查找元素的前驱与后继

在 BST 的中序遍历序列中,这两个元素分别紧邻 \(x\) 的左右两侧。

查找后继(Successor):寻找比 \(x\) 大的最小节点,分两种情况讨论:

(1)\(x\) 有右子树

  • 操作:前往 x.right,然后沿着 left 指针一直向下,直到尽头。

(2)\(x\) 没有右子树

这意味着以 \(x\) 为根的子树已经遍历完了。我们需要向上寻找,找到第一个“把 \(x\) 所在子树当做左子树”的祖先。 * 操作:沿着父节点 parent 向上找,直到发现某个节点 \(y\),使得其左孩子是 \(x\)(或者 \(x\) 的祖先)。此时 \(y\) 就是后继。

查找前驱(Predecessor):前驱的逻辑与后继完全对称

(1)\(x\) 有左子树

  • 操作:前往 x.left,然后沿着 right 指针一直向下,直到尽头。

(2)\(x\) 没有左子树

  • 操作:向上找父节点,直到发现某个节点 \(y\),使得其右孩子是 \(x\)(或者 \(x\) 的祖先)。

时间复杂度为 \(O(h)\)

元素的插入与删除(参考数据结构)


随机二叉搜索树(Randomized Binary Search Trees)

为确保树高尽可能小,避免搜索树退化成链,考虑随机化算法。

树堆Treap(BST+Heap)

每一个结点包含键值与优先级两个数

证明:若Treap中每一个结点的键值互不相同,优先级互不相同,则这个Treap是唯一的。

Treap不一定是二叉堆

第一种视角:Random-order BST insertions

按最小堆处理,优先级越低,越早插入

第二章视角:Quicksort recursion tree

仿照快速排序,每次选择优先级最小的元素作为界限进行划分,将这一过程表成树,即有限级最小的元素作为根节点,将左右元素划分到它的左右子树中,如此构造得到二叉搜索树。

详细证明:给定序列\(A[1,\cdots,n]\)和对应的随机优先级\(P[1,\cdots,n]\),类比快速排序过程,可知\(A[k]\)在二叉搜索树中的深度为\(A[k]\)与界限pivot的比较次数

\(A[k]\)\(A[i]\) 发生比较的概率: $\(\Pr \{A[k] \text{ compares with pivot } A[i]\} = \Pr \{P[i] = \min_{j \in [i, k]} \{P[j]\}\} \le \frac{1}{|k-i|}\)$

  1. 假设 \(A\) 数组已经按键值排好序。考虑 \(A[i]\)\(A[k]\) 之间的所有元素(包含端点),共有 \(|k-i|+1\) 个元素。
  2. 在快速排序或 Treap 构造中,\(A[i]\)\(A[k]\) 会发生比较,当且仅当 \(A[i]\)\(A[k]\) 是这 \(|k-i|+1\) 个元素中优先级 \(P\) 最小的(即最先被选为 pivot 的)。
  3. 如果该区间中任何一个中间元素 \(A[j]\) 先被选为 pivot,那么 \(A[i]\) 会被分到左区间,\(A[k]\) 会被分到右区间,它们此后永远不会被比较。 $\(\text{Expected comparisons} \le \sum_{i \neq k} \frac{1}{|k-i|} \le O(\log n)\)$

跳表(Skip List)