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

相关推荐
飞Link1 小时前
什么是 PX4?一文了解 PX4 在空地协同中的作用
算法·无人机
进化中的刀盾兽1 小时前
从零实现 C++ Json-Rpc(十):把消息交给真实连接——MuduoConnection 与 ConnectionFactory
c++·rpc
一去不复返的通信er7 小时前
力扣-图论-岛屿数量
算法·leetcode·图论
青瓦梦滋8 小时前
WebSocket协议
linux·服务器·网络·c++·websocket·网络协议·http
程序 代码狂人10 小时前
切片表与分区表的区别(数据开发面试版)
java·大数据·开发语言·数据仓库·算法
HDU-Dade11 小时前
【校招笔试真题】简要介绍 Self-Attention 的前沿算法
人工智能·算法
Zwawa12 小时前
编译器工具链:GCC、Clang、MSVC、ICC、armclang
c语言·嵌入式·编译器
学逆向的12 小时前
C 指针常量与常量指针
c语言·开发语言·网络安全
水饺编程13 小时前
第2章:Linux 基础,exit 命令
linux·c语言·汇编
小郎君65813 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
算法