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

C++二叉搜索树原理剖析与高效实现

二叉搜索树(BST)通过左子节点小于父节点、右子节点大于父节点的有序性实现高效查找与插入。了 BST 的结构定义、节点插入、中序遍历、查找、删除及析构等核心操作,提供了基于现代 C++ 的内存安全实现范式,并分析了拷贝构造逻辑,为平衡树学习奠定基础。

ArchDesign发布于 2026/3/26更新于 2026/10/2493 浏览
C++二叉搜索树原理剖析与高效实现

文章配图

文章配图

前引:二叉搜索树(Binary Search Tree, BST)作为一种基础且强大的数据结构,凭借其高效的查找与插入效率,成为算法设计与内存优化的核心工具。在 C++ 中,BST 不仅能实现高效的数据管理,更为平衡树(如 AVL 树)奠定理论基础。本文将深入剖析 BST 的有序性本质(结合 C++ 特性详解插入、删除、遍历等关键操作,并提供内存安全的现代 C++ 实现范式!

【一】二叉搜索树介绍

二叉搜索树又称二叉排序树,我们根据它的名字猜到是一颗二叉树完成了排序的工作?二叉树如何排序?下面我们来看看它和我们之前学习的大小顶堆有什么区别!

【二】特点剖析

例如下面一棵二叉搜索树(可以为空树):

文章配图

二叉搜索树语言描绘特征如下:

(1)从第一个父节点(根节点)开始,它的左子节点小于父节点

(2)从第一个父节点(根节点)开始,它的右子节点大于父节点

(3)它的左右子树也分别为二叉搜索树

【三】二叉搜索树实现

(1)结构创建

实现一棵二叉搜索树,我们需要一个节点结构、一个功能结构。

节点结构里面有左右子节点(left,right)、一个数据存储变量(data):

**注意:**主模板的声明不允许使用模板参数

功能结构用来实现二叉搜索树的功能:

(2)插入节点

插入节点我们需要根据数据的大小来判断插在左右节点的 nullptr 位置,这里挑战循环来写。

**注意:**我们需要用其它节点代替 node 去移动,不然 node 每次都不是指向根节点的。

// 插入节点
void Insert(const T& data) {
    // 如果根节点为空
    if (node == nullptr) {
        node = new Node(data);
        return;
    }
    // 根据数据大小查找
    Node* parent = ;
    Node* cur = node;
     (cur) {
        
        parent = cur;
        
         (data < cur->data) {
            cur = cur->left;
        }  {
            cur = cur->right;
        }
    }
    
    
     (data < parent->data) {
        
        parent->left =  (data);
        ;
    }  {
        
        parent->right =  (data);
        ;
    }
}
nullptr
while
// 记录父节点
// 如果小于父节点
if
else
// 此时已经到了节点为空的位置
// 如果小于父节点
if
// 插在父节点左侧
new
Node
return
else
// 插在父节点右侧
new
Node
return
(3)中序遍历

中序调用递归来完成:先遍历左子树,然后父节点,然后右子树。

// 中序遍历
void Inorder() {
    _Inorder(node);
}

void _Inorder(Node* ptr) {
    // 遇到空就返回
    if (ptr == nullptr) {
        return;
    }
    _Inorder(ptr->left);
    cout << ptr->data << " ";
    _Inorder(ptr->right);
}

效果展示:

(4)查找节点

找到对应节点之后,然后返回即可:根据要找的数据大小去查找,那么最多查找次数就是二叉树的深度次。

// 查找数据
bool Find(const T& data) {
    // 如果为空树,返回
    if (node == nullptr) {
        return false;
    }
    Node* cur = node;
    // 找节点
    while (cur) {
        // 如果 data 大于父节点,右边找,否则左边找
        if (data > cur->data) {
            cur = cur->right;
        } else if (data < cur->data) {
            cur = cur->left;
        } else {
            return true;
        }
    }
    // 如果出循环了还没有返回就说明没有找到
    return false;
}

效果展示:

(5)删除节点

删除节点我们需要考虑下面这三个情况(重点是比较节点数据大小):

(1)该节点无孩子节点:先删,然后置空

(2)该节点有一个孩子节点:先连接再删

**注意:**这两种情况可以概括为一类,参考下面代码注释,比较简单我们就直接看代码

(3)该节点有两个孩子节点:我们需要找一个合适大小的节点去替代它

替代思路:让它的左子树最大值或者右子树最小值去替换,然后删除它(左子树 max 为例)

·

**解释:**例如下面这幅图,我们要删除 3

(1)先找到目标节点 cur(3),然后找目标节点左子树的最大值 left_max

(2)交换目标节点 cur 和最大值 left_max 的数据

(3)这里需要标记 left_max 的父节点为 parent

第一种情况:

(4)因为找的是左子树的最大值,所以只可能父节点 parent 的右边还存在子节点,

  将它连接在 parent 的右边

(5)再将 cur 指向 left_max,删除

第二种情况:

(4)因为找的是左子树的最大值,可能 parent 的左边还存在子节点

(5)再将 cur 指向 left_max,删除

效果展示:

(6)析构

我们可以利用上面的'删除节点'+'根节点是否为空循环'来不断析构。

**注意:**上面我们的析构是利用第三方指针 cur 代替 node 删除的,所以当二叉树只有一个根节点删除后需要考虑置空,这样才可以利用到循环。

// 析构
~BST() {
    while (node) {
        Erase(node->data);
        cout << "删除成功" << endl;
    }
}

测试:

文章配图

(7)拷贝构造

拷贝构造我们可以利用递归遍历不断开新节点。

**注意:**递归左右节点时要连接起来,下面有详细的批注。

// 拷贝构造
BST(const BST<T>& ptr) {
    // 如果拷贝对象是空
    if (ptr.node == nullptr) {
        return;
    }
    // 这里的 ptr 是拷贝的对象,node 是待拷贝的对象的根节点
    node = Copy(node, ptr.node);
}

Node* Copy(Node* _node, Node* copy_node) {
    if (copy_node == nullptr) {
        return nullptr;
    }
    // 前序拷贝
    _node = new Node(copy_node->data);
    // 空间是开辟成功了,但是这里 node 的左右子树,没有连接,需要接收 copy 的返回值才能完成连接
    _node->left = Copy(_node->left, copy_node->left);
    _node->right = Copy(_node->right, copy_node->right);
    // 返回根节点
    return _node;
}

效果展示:

文章配图

目录

  1. 【一】二叉搜索树介绍
  2. 【二】特点剖析
  3. 【三】二叉搜索树实现
  4. (1)结构创建
  5. (2)插入节点
  6. (3)中序遍历
  7. (4)查找节点
  8. (5)删除节点
  9. (6)析构
  10. (7)拷贝构造

更多推荐文章

查看全部
  • Miloco 本地大模型智能家居部署与使用记录
  • Web Scraper 快速上手:网页数据批量采集指南
  • Z-Image-Turbo:输入文字秒出图的 AI 绘画工具解析
  • Ubuntu 本地部署 OpenClaw:接入 Ollama 推理与飞书通道
  • ExoPlayer 播放缓存进度监听方案实现
  • AI-Goofish-Monitor:闲鱼智能监控机器人指南
  • 别把 F1 开成老头乐:GitHub Copilot 深度调教与 7 个“上下文工程”秘籍
  • ASR 自动语音识别原理与 Whisper 模型详解
  • 攻防世界 Web 安全挑战题解与代码审计实战
  • Bing Webmaster 工具使用指南:添加、验证与提交站点地图
  • 使用 Web Workers 优化前端性能避免界面卡顿
  • 在大模型公司担任提示词工程师的职业体验与技术思考
  • 顺序表模拟实现与洗牌算法应用
  • 数据结构基础:单向链表实现与原理
  • Java LLM 开发框架全面解析:从 Spring AI 到 Agents-Flex
  • 越疆机器人 TCP 通讯 12 点标定脚本程序
  • OpenClaw 安装与飞书机器人接入教程
  • 基于 Dify 与 DeepSeek 构建智能问数 AI Agent 实践指南
  • 大模型 SFT 关键点解析与实践指南
  • 豆包 Seedream 4.0 多图融合能力测评:田园犬与三花猫多场景生成

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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