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 的原因)
谢谢

相关推荐
晚风吹红霞1 小时前
C++模板进阶:非类型参数、特化、分离编译与优缺点解析
开发语言·c++
吴可可1231 小时前
Win7下C#开发AutoCAD首选版本
算法
不会C语言的男孩2 小时前
C++ Primer 第8章:IO 库
开发语言·c++
Halo_tjn2 小时前
反射与设计模式2
java·开发语言·算法
磊 子2 小时前
C++仿函数以及STL内置仿函数
开发语言·c++
0x3F(小茶)2 小时前
嵌入式C设计模式完全指南(基于《C嵌入式编程设计模式》)
c语言·开发语言·单片机·嵌入式硬件·设计模式
王璐WL2 小时前
【C++进阶】map/multimap 容器详解:从基础使用到底层实现与高频面试题
c++
_日拱一卒2 小时前
LeetCode:46全排列
算法·leetcode·职场和发展
剑挑星河月2 小时前
31.下一个排列
java·算法·leetcode