跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 二叉搜索树实现与性能分析

综述由AI生成二叉搜索树(BST)是一种特殊的二叉树,左子树节点值小于根,右子树大于根。中序遍历可得升序序列。其查找、插入、删除平均时间复杂度为 O(logN),最坏退化为 O(N)。详细讲解了 BST 的节点定义、增删查改操作实现,包括处理左右子节点为空、单侧子节点及双侧子节点的删除策略。同时介绍了 Key 与 Key-Value 两种结构的应用场景,如车牌识别、拼写检查及字典查询等。

独立开发者发布于 2026/3/30更新于 2026/6/1129 浏览
C++ 二叉搜索树实现与性能分析

C++ 二叉搜索树实现与性能分析

一、概念与性能分析

二叉搜索树(Binary Search Tree, BST),又称二叉排序树。它要么是一棵空树,要么满足以下性质:

  • 若左子树不为空,则左子树上所有结点的值都小于等于根结点的值。
  • 若右子树不为空,则右子树上所有结点的值都大于等于根结点的值。
  • 左右子树本身也是二叉搜索树。

关于相等值的处理,取决于具体场景定义。例如 std::map/std::set 不支持插入相等键,而 multimap/multiset 支持。

性能表现

由于中序遍历必然得到升序序列,BST 非常适合有序数据的存储。其时间复杂度高度依赖于树的形态:

  • 最优情况:完全二叉树或接近完全二叉树,高度为 log2(N),增删查操作均为 O(log N)。
  • 最差情况:退化为单支树(类似链表),高度为 N,操作退化为 O(N)。

为了应对最坏情况,实际工程中常使用平衡二叉搜索树(如 AVL 树、红黑树)。相比二分查找,BST 的优势在于插入和删除效率更高,不需要像数组那样频繁移动数据,且支持动态扩容。

二、核心结构实现

1. 节点定义

为了方便访问成员,我们使用 struct 定义节点,默认公有权限。

template<class K> struct BSTreeNode {
    BSTreeNode* _left;
    BSTreeNode* _right;
    K _key;
    
    BSTreeNode(const K& key) :_left(nullptr), _right(nullptr), _key(key) {}
};

2. 类的基本框架

我们需要管理根节点指针,并处理资源的生命周期(构造、拷贝、析构)。

template<class K> class BSTree {
    typedef BSTreeNode<K> Node;
private:
    Node* _root = nullptr;
public:
    // 默认构造
    BSTree() = default;
    
    // 析构函数:递归释放内存
    ~BSTree() { Destroy(_root); }
    
    // 拷贝构造:深拷贝
    ( BSTree<K>& t) { _root = (t._root); }
    
    
    BSTree& =(BSTree t) {
        (_root, t._root);
         *;
    }
    
    
:
    ;
    ;
};
BSTree
const
Copy
// 赋值重载:交换法
operator
swap
return
this
// 辅助函数声明
private
void Destroy(Node* root)
Node* Copy(Node* root)

这里需要特别注意,由于涉及递归操作(如销毁、拷贝),私有成员 _root 无法在外部直接访问,因此必须封装私有辅助函数供公有接口调用。

3. 插入操作

插入逻辑遵循 BST 性质:比当前节点大往右走,小往左走,直到找到空位。

bool Insert(const K& key) {
    if (_root == nullptr) {
        _root = new Node(key);
        return true;
    }
    
    Node* cur = _root;
    Node* parent = nullptr;
    
    while (cur) {
        if (cur->_key < key) {
            parent = cur;
            cur = cur->_right;
        } else if (cur->_key > key) {
            parent = cur;
            cur = cur->_left;
        } else {
            // 已存在,根据需求决定是否允许重复
            return false;
        }
    }
    
    cur = new Node(key);
    if (parent->_key < key)
        parent->_right = cur;
    else
        parent->_left = cur;
        
    return true;
}

4. 查找操作

查找相对简单,利用 BST 的有序性剪枝。

bool Find(const K& key) {
    Node* cur = _root;
    while (cur) {
        if (cur->_key < key)
            cur = cur->_right;
        else if (cur->_key > key)
            cur = cur->_left;
        else
            return true;
    }
    return false;
}

5. 删除操作(难点)

删除是最复杂的操作,需分情况讨论:

  1. 无子节点:直接删除,父节点对应指针置空。
  2. 单子节点:父节点指针指向该节点的子节点。
  3. 双子节点:无法直接删除。通常用右子树的最小值(或左子树的最大值)替换当前节点的值,然后递归删除那个最小值节点(此时它必然是单子节点或叶子节点)。
bool Erase(const K& key) {
    Node* parent = nullptr;
    Node* cur = _root;
    
    while (cur) {
        if (cur->_key < key) {
            parent = cur;
            cur = cur->_right;
        } else if (cur->_key > key) {
            parent = cur;
            cur = cur->_left;
        } else {
            // 找到目标节点,开始删除逻辑
            if (cur->_left == nullptr) {
                // 左为空,处理右孩子或空
                if (cur == _root)
                    _root = cur->_right;
                else {
                    if (cur == parent->_left)
                        parent->_left = cur->_right;
                    else
                        parent->_right = cur->_right;
                }
                delete cur;
            } else if (cur->_right == nullptr) {
                // 右为空,处理左孩子
                if (cur == _root)
                    _root = cur->_left;
                else {
                    if (cur == parent->_left)
                        parent->_left = cur->_left;
                    else
                        parent->_right = cur->_left;
                }
                delete cur;
            } else {
                // 双孩子:找右子树最小值替代
                Node* pMinRight = cur;
                Node* minRight = cur->_right;
                while (minRight->_left) {
                    pMinRight = minRight;
                    minRight = minRight->_left;
                }
                
                // 交换值
                std::swap(minRight->_key, cur->_key);
                
                // 删除原最小值节点(此时必为单子节点或叶子)
                if (pMinRight->_left == minRight)
                    pMinRight->_left = minRight->_right;
                else
                    pMinRight->_right = minRight->_right;
                
                delete minRight;
            }
            return true;
        }
    }
    return false;
}

6. 中序遍历

验证 BST 是否有序的标准方法。

void InOrder() {
    _InOrder(_root);
    cout << endl;
}

private:
void _InOrder(Node* root) {
    if (root == nullptr) return;
    _InOrder(root->_left);
    cout << root->_key << " ";
    _InOrder(root->_right);
}

三、Key 与 Key-Value 结构扩展

上述实现仅存储 Key。在实际应用中,往往需要关联一个 Value,例如字典查询或统计词频。

1. 结构定义

namespace key_value {
template<class K, class V> struct BSTreeNode {
    BSTreeNode<K, V>* _left;
    BSTreeNode<K, V>* _right;
    K _key;
    V _value;
    
    BSTreeNode(const K& key, const V& value) 
        :_left(nullptr), _right(nullptr), _key(key), _value(value) {}
};
// 类实现逻辑与 Key 版本类似,只是节点多了一个 _value 成员
// 注意:Erase 时只根据 Key 删除,Value 随 Key 一起移除
} // namespace

2. 应用场景

  • Key 场景:车牌识别系统(判断是否在白名单)、拼写检查(单词是否存在于词典)。
  • Key-Value 场景:中英翻译字典(Key=英文,Value=中文)、停车场计费(Key=车牌,Value=入场时间)、词频统计(Key=单词,Value=次数)。

通过这种方式,二叉搜索树不仅实现了高效查找,还能灵活承载业务数据。

目录

  1. C++ 二叉搜索树实现与性能分析
  2. 一、概念与性能分析
  3. 性能表现
  4. 二、核心结构实现
  5. 1. 节点定义
  6. 2. 类的基本框架
  7. 3. 插入操作
  8. 4. 查找操作
  9. 5. 删除操作(难点)
  10. 6. 中序遍历
  11. 三、Key 与 Key-Value 结构扩展
  12. 1. 结构定义
  13. 2. 应用场景
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 大模型学习方法:从构建小应用入手而非沉迷理论
  • 鸿蒙金融理财全栈项目:生态合作、用户运营与数据变现
  • SketchUp STL 插件安装与使用指南
  • Linux 进程间通信:命名管道(FIFO)原理与实战
  • CUDA C++ 基础介绍
  • SpringBoot 集成 MinIO 文件服务器配置与使用
  • 网络安全行业前景深度解析与入行路径建议
  • C++ 类与对象进阶:默认成员函数与操作符重载
  • C/C++ 内存管理与动态分配核心解析
  • ERNIE-4.5-0.3B 轻量化部署与效能优化实战
  • Trae AI 编辑器安装与核心功能使用指南
  • 使用 AList 挂载网盘在 PICO 头显观看 VR 电影
  • Coze AI 智能体开发入门:零基础搭建专属 AI 应用
  • PyCharm 启动报错 Archived non-system classes are disabled 解决方案
  • Java 8 函数式编程实战:Lambda、Stream 与 Optional 详解
  • C++ Qt 网络编程:QUdpSocket、QTcpSocket 与 Http 实战
  • 鸿蒙APP开发:服务联邦跨服务无缝打通
  • Java三件套:JDK、JRE、JVM详解
  • ToClaw 深度体验:AI 如何从聊天走向任务执行
  • 国外清淤机器人应用案例与实践经验

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online