首页/数据结构/04-tree/二叉排序树(BST) 🔗 在 Obsidian 中打开
数据结构 · 树与二叉树

二叉排序树(BST, Binary Search Tree)

难度 ★★重要度 ★★ 考查频率 中 二叉排序树二叉搜索树查找408
速查
二叉排序树(BST):左子树所有结点值 < 根,右子树所有结点值 > 根(递归成立)。结论:中序遍历得到递增序列。查找/插入平均 $O(\log n)$,最坏退化成链 $O(n)$。

核心概念

二叉排序树(BST,也称二叉搜索树)或者是一棵空树,或者是满足下列性质的二叉树:

  • 若左子树非空,则左子树上所有结点的值都小于根结点的值;
  • 若右子树非空,则右子树上所有结点的值都大于根结点的值;
  • 左、右子树也分别是二叉排序树。
最重要推论对 BST 做中序遍历(左→根→右),得到的结点序列是严格递增的。这是验证一棵二叉树是否为 BST 的常用方法。

查找 / 插入 / 删除

查找

从根开始,与目标值比较:相等则找到;小于当前结点则进入左子树;大于则进入右子树,直到空(失败)。

插入

沿查找路径下到“应插入位置的父结点”,作为叶子插入(BST 的新结点总是叶子)。

删除(三种情况)

  1. 叶子结点:直接删除。
  2. 只有一棵子树:用子树代替被删结点。
  3. 有两棵子树:用直接前驱(左子树最右结点)或直接后继(右子树最左结点)替换被删结点,再删除那个前驱/后继。
// 查找(递归)
BiTNode *SearchBST(BiTree T, int key) {
    if (!T || key == T->data) return T;
    if (key < T->data) return SearchBST(T->lchild, key);
    else return SearchBST(T->rchild, key);
}

构造示例

依次插入 50, 30, 70, 20, 40, 60, 80 得到如下 BST:

50 30 70 20 40 60 80
图:插入序列 50,30,70,20,40,60,80 后得到的 BST(中序为 20,30,40,50,60,70,80)。

中序遍历得到 20, 30, 40, 50, 60, 70, 80,递增,符合 BST 性质。

关键性质

  • 中序遍历结果严格递增。
  • 查找、插入、删除的平均时间复杂度 $O(\log n)$(树高)。
  • 若插入序列有序(如 1,2,3,…),BST 退化成斜树/链表,最坏 $O(n)$。
  • 平均查找长度 $ASL \approx \log_2 n$(接近最佳),最坏为 $(n+1)/2$。
退化的代价正因为 BST 可能退化,才需要 AVL 树、红黑树等自平衡结构来约束树高。

常见考法

题型① 给定插入序列画出 BST;② 给定 BST 写出中序序列判断合法性;③ 删除某结点(尤其有两子树的情形,用前驱/后继替换);④ 计算 ASL。

易错点

必记
  1. 删除“有两子树”的结点时,要用直接前驱或直接后继替换,不能直接用任意孩子。
  2. “中序有序”只能说明是 BST 的必要条件,但中序递增的二叉树一定是 BST(这里等价)。
  3. “等于”的情况通常放入右子树或不允许重复键,由实现约定决定。
  4. BST 最坏情况是有序插入退化为链表,不要默认 $O(\log n)$。

核心结论

要点结论
定义左 < 根 < 右(递归)
中序遍历严格递增序列
查找/插入/删除(平均)$O(\log n)$
最坏$O(n)$(退化成链)

记忆卡片

BST 的中序序列有什么特点?
严格递增(或递减,取决于约定)。
删除有两子树的结点怎么办?
用直接前驱(左子树最右)或直接后继(右子树最左)替换。
为什么 BST 可能退化?
有序插入会退化成斜树,最坏查找 O(n)。
平均查找长度?
平均约 log₂n,最坏 (n+1)/2。

交互动画 · BST 查找路径

50 30 70 20 40 60 80
点击上方按钮,观察从根 50 出发沿 BST 性质向下比较的查找路径

相关知识点

binary-tree-traversal avl-tree huffman-tree-and-encoding search-algorithm-comparison

↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。