c/c++中的二叉树进阶

1. 二叉搜索树

二叉搜索树(Binary Search Tree,简称 BST) 也叫二叉排序树,是最基础的有序树形结构,C++ std::map 的底层雏形(标准库用红黑树 = 平衡版 BST),核心特点:有序、快速查找、插入、删除。

1.核心性质

满足4 条铁律,就是二叉搜索树:

1.左子树的所有节点值 < 根节点值

2.右子树的所有节点值 > 根节点值

3.左、右子树也必须是二叉搜索树

4.中序遍历结果 = 升序有序序列(最核心特性!)

无重复节点值(和 map 的 key 唯一一致)

这就是一颗标准的二叉搜索树:

中序遍历:2 → 3 → 4 → 5 → 6 → 7 → 8(严格升序)

2.、三大核心操作

1. 查找操作

规则:

值 < 根 → 查左子树

值 > 根 → 查右子树

值 = 根 → 找到

到空节点 → 没找到

cpp 复制代码
// 递归查找
Node* search(Node* root, int target) {
    // 空树/没找到
    if (root == nullptr) return nullptr;
    // 找到目标
    if (root->val == target) return root;
    // 目标更小,查左子树
    if (target < root->val) return search(root->left, target);
    // 目标更大,查右子树
    else return search(root->right, target);
}
2.插入操作

规则:查找的过程中,找到空位置直接插入,保证有序。

插入后依然满足 BST 性质

重复值不插入(保持唯一)

cpp 复制代码
// 递归插入
Node* insert(Node* root, int val) {
    // 找到空位置,创建新节点
    if (root == nullptr) return new Node(val);
    
    // 值已存在,不插入
    if (val == root->val) return root;
    
    // 值更小,插入左子树
    if (val < root->val) root->left = insert(root->left, val);
    // 值更大,插入右子树
    else root->right = insert(root->right, val);
    
    return root;
}
3. 删除操作

删除后必须保持 BST 有序,分三种场景:

情况 1:删除叶子节点(无孩子)

直接删除,置空即可。

例:删除 2、4、6、8

情况 2:删除只有一个孩子的节点

用孩子节点替代被删节点。

例:删除只有左 / 右孩子的节点

情况 3:删除有两个孩子的节点(核心)

找后继节点(右子树的最小值) 替代,再删除后继节点。

例:删除根节点 5 → 用 6 替代

cpp 复制代码
// 找右子树的最小值(后继节点)
Node* getMin(Node* node) {
    while (node->left) node = node->left;
    return node;
}

// 递归删除节点
Node* remove(Node* root, int val) {
    if (root == nullptr) return nullptr;

    // 查找要删除的节点
    if (val < root->val) root->left = remove(root->left, val);
    else if (val > root->val) root->right = remove(root->right, val);
    // 找到待删除节点
    else {
        // 情况1:无孩子(叶子节点)
        if (root->left == nullptr && root->right == nullptr) {
            delete root;
            return nullptr;
        }
        // 情况2:只有一个孩子
        else if (root->left == nullptr) {
            Node* temp = root->right;
            delete root;
            return temp;
        }
        else if (root->right == nullptr) {
            Node* temp = root->left;
            delete root;
            return temp;
        }
        // 情况3:两个孩子 → 找右子树最小值替代
        else {
            Node* minNode = getMin(root->right);
            root->val = minNode->val;                // 替换值
            root->right = remove(root->right, minNode->val); // 删除后继节点
        }
    }
    return root;
}

3.时间复杂度

操作 平均情况 最坏情况(退化成链表)
查找 O(log n) O(n)
插入 O(log n) O(n)
删除 O(log n) O(n)

致命缺陷:

如果插入有序数据(1→2→3→4→5),BST 会退化成链表,效率暴跌。

和红黑树的关系:

二叉搜索树:不平衡,最坏 O (n)

红黑树:自平衡二叉搜索树,永远保持 O (log n)

std::map 底层 = 红黑树(不用普通 BST 的原因)
谢谢

相关推荐
To_OC1 小时前
从一次栈溢出报错说起,我把递归彻底扒明白了
javascript·算法·程序员
千纸鹤安安6 小时前
千问Qwen-AgentWorld来了:一个语言模型搞定七大Agent场景,GPT-5.4都输了
算法
七牛开发者8 小时前
MCP 到底是什么?为什么 Agent 都想接上它
算法·aigc·agent
卷无止境13 小时前
C++ 的Eigen 库全解析
c++
卷无止境13 小时前
现代 C++特性大盘点:一门脱胎换骨的老语言
c++·后端
郝学胜_神的一滴14 小时前
CMake 27:缓存变量的特性、语法、类型与实操全解
c++·cmake
kisshyshy15 小时前
从递归到迭代,一文吃透二叉树的核心知识与 JavaScript 实现
javascript·算法·代码规范
To_OC1 天前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode