相关笔记

概览

本节介绍二叉搜索树(Binary Search Tree, BST)的基本定义与核心性质。BST是一种支持动态集合操作的二叉树数据结构,每个节点存储一个关键字,并满足BST性质:对于任意节点 ,其左子树中所有关键字 右子树中所有关键字 。利用这一性质,可以在 时间内完成搜索、最小值、最大值、前驱、后继等操作,其中 为树高。本节重点阐述BST的递归定义、中序遍历的有序性证明(定理12.1),以及BST与其他数据结构的对比分析。


知识结构总览

flowchart TD
    A["二叉搜索树 BST"] --> B["BST递归定义"]
    A --> C["BST性质"]
    A --> D["中序遍历 INORDER-TREE-WALK"]
    A --> E["定理12.1:中序遍历输出有序序列"]

    B --> B1["节点结构:key, left, right, parent"]
    B --> B2["左子树所有key ≤ 节点key"]
    B --> B3["右子树所有key ≥ 节点key"]

    C --> C1["全局约束:整个子树,非仅直接孩子"]
    C --> C2["允许重复关键字"]

    D --> D1["递归:先左子树 → 当前节点 → 右子树"]
    D --> D2["时间复杂度 Θ(n)"]

    E --> E1["数学归纳法证明"]
    E --> E2["归纳基础:空子树"]
    E --> E3["归纳步骤:左子树 + 根 + 右子树有序拼接"]

核心思想

核心思路

二叉搜索树的核心思想是将二分查找的思想嵌入到树形结构中。在有序数组上做二分查找时,每次比较将搜索空间缩小一半;类似地,在BST中,每次与节点关键字的比较都会将搜索引导到左子树或右子树,从而在 时间内定位目标。BST的优势在于它同时支持高效的搜索动态插入/删除(后续章节展开),这是静态有序数组无法做到的。BST性质是这一切的基石——它保证以中序遍历访问树中所有节点时,输出的是一个非递减序列

BST的递归定义

二叉搜索树是按如下方式组织的二叉树:

  • 每个节点是一个对象,包含关键字 key、左孩子指针 left、右孩子指针 right、父节点指针 parent
  • 若某属性(如左孩子)不存在,则对应属性值为 NIL
  • 为树中的一个节点:
    • 左子树中,则
    • 右子树中,则

BST性质(Binary-Search-Tree Property)

为二叉搜索树中的一个节点。如果 左子树中的一个节点,那么 。如果 右子树中的一个节点,那么

关键强调: BST性质是一个全局约束,它约束的是整个子树中的所有节点,而不仅仅是节点的直接孩子。例如,节点 的左孩子的右孩子的右孩子……的关键字也必须

INORDER-TREE-WALK —— 伪代码

INORDER-TREE-WALK(x)
1  if x ≠ NIL
2      INORDER-TREE-WALK(x.left)
3      print x.key
4      INORDER-TREE-WALK(x.right)

该过程按照左子树 → 当前节点 → 右子树的顺序递归访问每个节点。当 时递归终止,无需额外处理。

定理12.1:中序遍历输出有序序列

定理12.1

如果 是一棵有 个节点的二叉搜索树的根,那么调用 将在 时间内输出这 个关键字的一个非递减序列

【BST中序遍历有序性(强归纳法:左子树+根+右子树有序拼接)】

证明(数学归纳法):

我们对 为根的子树的大小(节点数)进行强归纳法

循环不变式(归纳假设)

对任意以 为根的子树, 输出该子树中所有关键字的非递减序列。

归纳基础: 当子树为空()时,过程不执行任何操作,空序列显然是非递减的。归纳基础成立。

归纳步骤: 假设对大小不超过 的任意子树,归纳假设成立。考虑以 为根、大小为 的子树。

  1. 由 BST 性质, 左子树中所有关键字 右子树中所有关键字
  2. 的左子树和右子树的大小均不超过 ,由归纳假设:
    • 输出左子树所有关键字的非递减序列
    • 输出右子树所有关键字的非递减序列
  3. 中序遍历的输出为 ,然后 ,然后
  4. 由于 中每个元素 中每个元素,且 各自非递减,因此拼接后的完整序列也是非递减的

归纳步骤成立。由强归纳法,定理得证。

时间复杂度分析

时间复杂度

的时间复杂度为 ,其中 为树中节点数。原因如下:

  • 过程对每个节点恰好访问一次(第2行递归进入、第3行打印、第4行递归进入),每次访问执行 操作
  • 因此总时间为

注意:该复杂度与树的具体形状无关,无论树是平衡的还是退化为链表,中序遍历都是


补充理解与拓展

BST的发明历史与自平衡树的演进

二叉搜索树作为一种数据结构的思想可追溯到1950年代,但真正使其成为实用数据结构的是1960年代的自平衡树研究。

1962年——AVL树: 苏联数学家 G. M. Adelson-VelskyE. M. LandisDoklady Akademii Nauk SSSR 上发表了论文”An algorithm for the organization of information”(Dokl. Akad. Nauk SSSR, 146(2):263–266, 1962),提出了AVL树——最早的自平衡二叉搜索树。AVL树通过”平衡因子”(左右子树高度差不超过1)维持平衡,插入和删除后通过最多 次旋转恢复平衡,保证所有操作在最坏情况下 1

1972年——B树: Rudolf BayerActa Informatica 上发表了”Symmetric binary B-trees: Data structure and maintenance algorithms”(Acta Informatica, 1(4):290–306, 1972),提出了对称二叉B树,后来演变为红黑树2

1978年——红黑树命名: Leonidas J. GuibasRobert SedgewickSODA 上正式引入了”红黑树”这一名称和颜色编码方案,通过5条性质近似平衡BST,插入和删除仅需最多3次旋转。红黑树后来成为Java TreeMap、C++ std::map、Linux内核rbtree等广泛使用的实现基础。

1993年——左倾红黑树: Robert Sedgewick 提出了左倾红黑树(Left-Leaning Red-Black Tree),简化了实现(仅需2种旋转而非4种),成为算法教学和工程实践中的主流方案。

BST vs 散列表 vs 排序数组——工程视角的全面对比

三种数据结构各有优劣,选择取决于具体场景:

比较维度BST(平衡时)散列表排序数组
搜索 最坏 平均, 最坏
插入 平均
删除 平均
最小/最大值 需遍历
前驱/后继不支持
范围查询不支持
顺序遍历 中序 需排序
是否有序天然有序无序天然有序
缓存性能差(指针跳跃)中等(链地址)优(连续内存)

工程实践中的选择:

  • JavaHashMap(散列)用于无序快速查找,TreeMap(红黑树)用于有序操作
  • C++std::unordered_map(散列)用于默认场景,std::map(红黑树)用于需要有序遍历的场景
  • 数据库:MySQL InnoDB使用B+树(BST的推广)作为索引,因为磁盘IO的特性使得B+树的宽扇出比平衡BST的高度更重要
  • 语言内置排序:Python的dict使用散列表,而sortedcontainers库提供基于BST的有序字典

BST的核心优势在于:同时支持高效的动态修改和有序性查询。散列表虽然平均查找更快,但无法支持范围查询和有序遍历;排序数组虽然缓存友好,但动态修改代价高昂。3


易混淆点与辨析

BST性质是全局约束,不是仅对直接孩子的约束

❌ 错误理解:BST性质只要求 ,即只约束直接孩子。

✅ 正确理解:BST性质约束的是整个子树。例如, 左子树中所有节点(包括左孩子的右孩子、左孩子的左孩子的右孩子等)的关键字都必须 。如果只约束直接孩子,那么可能构造出左孩子的右孩子大于 的”假BST”,此时中序遍历将不再输出有序序列。

重复关键字的处理策略

❌ 错误理解:BST中不允许出现重复的关键字。

✅ 正确理解:CLRS采用的BST性质定义允许重复关键字(左子树 ,右子树 )。不同实现对此有不同策略:

  • CLRS策略:允许重复,左子树 右子树
  • 严格策略:不允许重复,左子树 右子树
  • 计数策略:每个节点增加 count 字段记录重复次数

在实际应用中,需根据具体需求选择策略。本笔记统一采用CLRS的定义。


习题精选

题号题目描述难度考察重点
12.1-1在图12-1(a)的二叉搜索树中搜索关键字13,列出依次访问的节点序列BST搜索路径
12.1-2假设BST中各关键字互不相同,证明:最小元素没有左孩子,最大元素没有右孩子⭐⭐BST性质推导
12.1-3用归纳法证明:具有 个内部节点的二叉搜索树中,外部节点(NIL)的个数为 ⭐⭐二叉树结构性质
12.1-4给定关键字序列 {5, 2, 9, 1, 3, 7},画出依次插入空BST后的结果BST插入过程
12.1-5证明:对BST的根调用INORDER-TREE-WALK,输出序列恰好是所有关键字按非递减序排列⭐⭐定理12.1理解

视频学习指南

资源主题链接说明
MIT 6.006 Lecture 5Binary Search Treeshttps://www.youtube.com/watch?v=9Jry5-82IqMErik Demaine讲解BST基本操作,含动画演示
MIT 6.006 Lecture 6Balanced BSTs (AVL)https://www.youtube.com/watch?v=FNeL18KsWPc从BST过渡到平衡树,理解BST的局限性
Abdul BariBinary Search Treehttps://www.youtube.com/watch?v=H5JubkIy_pI直观的BST插入和搜索动画,适合入门
Stanford CS106BBSThttps://www.youtube.com/watch?v=CozKR3eF7qYStanford课程中的BST讲解,注重编程实现
mycodeschoolBST Introductionhttps://www.youtube.com/watch?v=pmTn_0cPbGk清晰的BST概念讲解与代码实现

教材原文

CLRS 第4版 12.1节原文

二叉搜索树(binary search tree)是按如下方式组织的二叉树:每个节点是一个对象,除了关键字(key)和相关卫星数据外,还包含属性 left、right 和 parent,分别指向该节点的左孩子、右孩子和父节点。如果某个孩子节点或父节点不存在,则相应属性的值为 NIL。根节点是树中唯一父节点属性为 NIL 的节点。

二叉搜索树中的关键字总是满足二叉搜索树性质:设 为树中的一个节点。如果 左子树中的一个节点,那么 。如果 右子树中的一个节点,那么

过程 INORDER-TREE-WALK 按中序遍历整棵子树。如名字所示,该过程输出以 为根的子树中所有关键字的非递减序列。


参见Wiki

章节导航:

关联知识:

第12章-二叉搜索树 什么是二叉搜索树

Footnotes

  1. Adelson-Velsky, G. M., & Landis, E. M. (1962). “An algorithm for the organization of information.” Doklady Akademii Nauk SSSR, 146(2), 263–266.

  2. Bayer, R. (1972). “Symmetric binary B-trees: Data structure and maintenance algorithms.” Acta Informatica, 1(4), 290–306.

  3. Sedgewick, R., & Wayne, K. (2011). Algorithms, 4th Edition. Addison-Wesley. Princeton COS 226 Lecture Notes: “3.2 Binary Search Trees” 与 “3.4 Hash Tables”.