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

一、二叉搜索树 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. 删除三种情况是面试高频考点,必须熟练
相关推荐
程序员黑豆2 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
GreenTea3 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
风流 少年3 小时前
Spring AI 2.0:Memory
java·后端·spring
码匠许师傅3 小时前
【C++ 面试真题】聊聊 C++ 的移动语义与右值引用
java·c++·面试
2603_965148114 小时前
如何解析JSON数据?API返回的商品信息处理教程
开发语言·数据库·python·自动化·json·api
小席是个热心肠4 小时前
AI相关的自我学习
java·人工智能·学习
fqq34 小时前
力扣刷题前置Java语法
算法·leetcode·职场和发展
知无不研6 小时前
lambda表达式的使用(3)
开发语言·c++·lambda
数智化管理手记6 小时前
海量数据如何沉淀有效数据资产?数据标准化治理方案如何搭建?
java·大数据·人工智能
2501_906565126 小时前
数学之美探究
算法