二叉搜索树

二叉搜索树(Binary Search Tree,BST)是带有序性的二叉树:任意节点都满足「左子树所有节点 < 根 < 右子树所有节点」。它让查找像二分一样每次砍掉一半,平均复杂度 O(log n),是理解 AVL、红黑树等平衡树以及有序集合实现的基础。

基本性质

BST 的关键性质是中序遍历得到递增序列,常用它来验证一棵树是否为 BST,也可以直接当作排序工具。

        8
       / \
      3   10
     / \    \
    1   6    14
       / \
      4   7

对上面这棵树做中序遍历:1 3 4 6 7 8 10 14,正好从小到大。

查找与插入

查找从根开始:目标比当前节点小就走左子树,大就走右子树,相等即命中。插入按同样的比较规则一路找空位,新节点总是挂在叶子位置,插入后仍是 BST。

def search(root, val):
    if root is None or root.val == val:
        return root            # 找到或到底未找到
    if val < root.val:
        return search(root.left, val)   # 去左子树
    return search(root.right, val)      # 去右子树

def insert(root, val):
    if root is None:
        return Node(val)       # 找到空位,生成新节点
    if val < root.val:
        root.left = insert(root.left, val)
    elif val > root.val:
        root.right = insert(root.right, val)
    return root                # 相等时不做任何事(去重)

删除节点

删除分三种情况:

  • 叶子节点:直接删除即可。
  • 只有一个孩子:让孩子顶替被删节点。
  • 有两个孩子:用「右子树的最小节点」或「左子树的最大节点」替换被删节点,再删掉那个替身(它最多只有一个孩子)。
删除值为 3 的节点(有两个孩子):
        8                        8
       / \                      / \
      3   10    用右子树最小    4   10
     / \    \   值 4 替换     / \    \
    1   6    14  再删替身    1   6    14
       / \
      4   7

退化与自平衡

若按升序依次插入(1、2、3、4…),BST 会退化成一条链,查找复杂度退化为 O(n)。解决办法是让树保持平衡:AVL 树要求左右子树高度差不超过 1,红黑树用颜色规则保证近似平衡,使树高始终约为 log n。Java 的 TreeMap、C++ 的 map 内部正是红黑树,都是「BST + 自平衡」的工程实现。

复杂度与面试要点

操作平均最坏(退化成链)
查找O(log n)O(n)
插入O(log n)O(n)
删除O(log n)O(n)
  • 高频题:验证二叉搜索树(中序递增)、BST 第 K 小元素、把有序数组转成平衡 BST。
  • 答 BST 删除时先分「叶子 / 单孩子 / 双孩子」三情况,双孩子用替身节点,思路就清晰。
  • 能说出「有序插入会导致退化,因此工程上用平衡树」是重要的加分点。

小结:BST 用「左小右大」换来二分式的查找效率,前提是不退化;中序有序、插入即叶子、平衡化这三个关键词足以串起全部考点。

笔记加载中…