二叉搜索树:高效增删查的秘诀

一、二叉搜索树 BST 定义

二叉搜索树(Binary Search Tree)满足核心规则:

  1. 左子树所有节点值 < 根节点值
  2. 右子树所有节点值 > 根节点值
  3. 左右子树也同样满足以上规则

关键特性:BST 中序遍历结果 = 升序有序数组

二、节点结构

和普通二叉树节点完全一致:

复制代码
struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

三、BST 查找操作

思路

  • 比当前节点小 → 去左子树
  • 比当前节点大 → 去右子树
  • 相等 → 找到
  • 走到空 → 不存在

cpp

运行

复制代码
// 递归查找
TreeNode* searchBST(TreeNode* root, int val)
{
    if(!root || root->val == val)
        return root;

    if(val < root->val)
        return searchBST(root->left, val);
    else
        return searchBST(root->right, val);
}

四、BST 插入操作

思路

按大小找位置,遇到空节点直接新建节点挂上。

复制代码
TreeNode* insertBST(TreeNode* root, int val)
{
    // 找到空位置,新建节点
    if(!root)
        return new TreeNode(val);

    if(val < root->val)
        root->left = insertBST(root->left, val);
    else if(val > root->val)
        root->right = insertBST(root->right, val);
    
    // 相等不插入
    return root;
}

五、BST 删除操作(面试重点)

分三种情况:

  1. 叶子节点:直接删除

  2. 只有左 / 只有右子树:用子树顶替自己

  3. 左右都有子树 :找右子树最小值左子树最大值 替换,再删替补节点

    // 找右子树最小值节点
    TreeNode* getMin(TreeNode* root)
    {
    while(root->left)
    root = root->left;
    return root;
    }

    TreeNode* deleteBST(TreeNode* root, int val)
    {
    if(!root) return nullptr;

    复制代码
     if(val < root->val)
     {
         root->left = deleteBST(root->left, val);
     }
     else if(val > root->val)
     {
         root->right = deleteBST(root->right, val);
     }
     else
     {
         // 情况1:叶子 / 只有单孩子
         if(!root->left) return root->right;
         if(!root->right) return root->left;
    
         // 情况2:左右都有孩子,拿右子树最小值顶替
         TreeNode* minNode = getMin(root->right);
         root->val = minNode->val;
         root->right = deleteBST(root->right, minNode->val);
     }
     return root;

    }

六、中序遍历验证有序性

cpp

运行

复制代码
void inOrder(TreeNode* root)
{
    if(!root) return;
    inOrder(root->left);
    cout << root->val << " ";
    inOrder(root->right);
}

七、完整测试代码

复制代码
#include <iostream>
using namespace std;

// 复制上面节点、查找、插入、删除、中序遍历函数

int main()
{
    TreeNode* root = nullptr;
    // 插入构建BST
    root = insertBST(root,5);
    insertBST(root,3);
    insertBST(root,7);
    insertBST(root,2);
    insertBST(root,4);

    cout << "BST中序遍历(升序):";
    inOrder(root);
    cout << endl;

    // 删除节点3
    root = deleteBST(root,3);
    cout << "删除3后中序遍历:";
    inOrder(root);

    return 0;
}

八、BST 适用场景

  1. 自动排序、有序数据维护
  2. 高效查找、插入、删除 O (logn)
  3. C++ map /set 底层基于红黑树(平衡 BST)
  4. 笔试面试常考手写 BST 增删查

九、易错点总结

  1. 忽略 BST 左小右大规则
  2. 删除左右都有子树的节点不会找替补节点
  3. 插入重复值不做判断,破坏 BST 结构
  4. 忘记中序遍历一定升序这个特性

十、今日总结

  1. BST 核心规则:左小右大
  2. 中序遍历天然升序
  3. 掌握查找、插入、删除三套递归模板
  4. 删除三种情况是面试高频考点,必须熟练
相关推荐
集成显卡14 小时前
Rust实战七 |基于带 colored 颜色文字控制台的批量文件删除工具
开发语言·后端·rust
刀法如飞15 小时前
AI时代:DDD领域驱动建模与Ontology语义建模的区别
java·设计模式·架构
jeffer_liu15 小时前
Spring AI 生产级实战:工具调用
java·人工智能·后端·spring·ai编程
比昨天多敲两行15 小时前
linux 线程概念与控制
java·开发语言·jvm
huaweichenai15 小时前
php 根据每个类型的抽签范围实现抽签功能
开发语言·php
8Qi815 小时前
LeetCode 75:颜色分类(荷兰国旗问题)—— Java 题解 ✅
java·算法·leetcode·指针·排序
zzhongcy15 小时前
@Transactional 同类内部调用失效 + 两种自代理解决方案
java
AutumnWind042016 小时前
【Intelij IDEA使用手册】
java·ide·intellij-idea
codeejun16 小时前
每日一Go-73、云原生成本优化 —— 资源限制 & 指标驱动扩容
开发语言·云原生·golang
888CC++17 小时前
如何在 C 语言中进行程序调试?
前端·javascript·算法