从零开始掌握二叉搜索树(C++ 完整实现与深度解析)
二叉搜索树Binary Search Tree, BST是最基础、最经典的树形数据结构之一。它不仅是理解更高级树结构如 AVL 树、红黑树、B 树的基石在许多实际场景中也直接发挥作用。本文将从定义出发手把手带你用 C 实现一个完整的二叉搜索树并深入分析其性能与局限。一什么是二叉搜索树二叉搜索树 是一种特殊的二叉树它满足以下性质1若左子树非空则左子树上所有节点的值 均小于 根节点的值。2若右子树非空则右子树上所有节点的值 均大于 根节点的值。3左、右子树本身也各是一棵二叉搜索树。通常我们默认树中不存在值相等的节点若需支持重复键值可通过计数或规则约定处理本文以无重复为例。得益于这种有序性BST 能够以 O(h)的时间完成查找、插入、删除操作其中 h 是树的高度。最优情况下 hlog⁡n退化为链表时 hn。二节点定义与基本框架我们用 C 模板来实现以便支持不同数据类型。节点结构包含数据域、左右孩子指针。为便于管理内存这里使用原始指针并在析构函数中递归释放整棵树。templateclass T struct TreeNode { T _key; TreeNodeT* _left; TreeNodeT* _right; TreeNode(const T key) :_key(key) , _left(nullptr) ,_right(nullptr) { } }; templateclass T class BSTree { struct Less { bool operator()(const T x, const T y) { return x y; } }; struct Greater { bool operator()(const T x, const T y) { return x y; } }; typedef TreeNodeT Node; public: BSTree() :_root(nullptr) { } ~BSTree() { _postorder_traversal(_root); } private: void _postorder_traversal(Node* root) { if (root nullptr) return; _postorder_traversal(root-_left); _postorder_traversal(root-_right); delete root; } Node* _root;一查找从根节点开始若目标值等于当前节点值则找到若小于则进入左子树若大于则进入右子树。递归与非递归版本都很简洁。bool find(const T key)const { if (_root nullptr) return false; Node* root _root; while (root) { if (key root-_key) { root root-_left; } else if (key root-_key) { root root-_right; } else { return true; } } return false; }二插入插入的过程与查找类似寻找合适的位置即查找失败时所在的空位然后将新节点挂载上去。下图展示了插入的过程。bool insert(const T key) { Node* root _root; Node* parent nullptr; while (root) { if (Less()(key, root-_key)) { parent root; root root-_left; } else if (Greater()(key, root-_key)) { parent root; root root-_right; } else { return false; } } Node* newnode new Node(key); if (_root nullptr) { _root newnode; } else { if (Less()(key, parent-_key)) parent-_left newnode; else parent-_right newnode; } return true; }三删除删除操作需要处理三种情况1叶子节点直接删除。2只有一个孩子用其孩子替换该节点。3有两个孩子找到 后继节点左右都不为空找到左子树的最大节点或者右子树的最小节点本文是找左子树的最大节点右子树最小节点同理。然后将要删除的值与该节点的值交换交换之后再将其删除。bool erase(const T key) { Node* node _root; Node* parent nullptr; while (node) { if (key node-_key) { parent node; node node-_left; } else if (key node-_key) { parent node; node node-_right; } else { if (node-_left nullptr) { if (parent nullptr) _root _root-_right; else { if (parent-_left node) parent-_left node-_right; else parent-_right node-_right; } delete node; return true; } else if (node-_right nullptr) { if (parent nullptr) _root _root-_left; else { if (parent-_left node) parent-_left node-_left; else parent-_right node-_left; } delete node; return true; } else { //左右都不为空找到左子树的最大节点或者右子树的最小节点 Node* maxleft node-_left; Node* maxleftparent node; while (maxleft-_right) { maxleftparent maxleft; maxleft maxleft-_right; } swap(node-_key, maxleft-_key); if (maxleftparent-_left maxleft) maxleftparent-_left maxleft-_left; else maxleftparent-_right maxleft-_left; delete maxleft; return true; } } } return false; }三性能分析与退化问题理想情况下BST 高度 h≈log⁡2nh≈log2​n查找、插入、删除时间复杂度均为 O(log⁡n)O(logn)。但如果插入序列本身有序如1,2,3,4,5BST 将退化为一根“向右的链表”树高变为 nn时间复杂度恶化为 O(n)O(n)。这是基础 BST 的最大痛点。解决办法是使用 自平衡二叉搜索树如1AVL 树严格平衡左右子树高度差不超过 1查找极快但插入/删除旋转开销稍大。2红黑树近似平衡最长路径不超过最短路径的两倍综合性能优异是c std::map和std::set 的底层实现。3Treap、Splay 树利用随机优先级或访问局部性进行平衡。理解 BST 是进阶这些平衡树的前提。四总结二叉搜索树将“二分查找”的思想扩展到了动态数据结构上实现简单且功能强大。它让我们看到仅仅通过维护“左小右大”这一简单的规则就能高效组织、检索数据。而其退化的缺陷又顺理成章地引出了平衡树等数据结构。

相关新闻

QQ空间数据备份终极指南:如何一键导出你的青春记忆

QQ空间数据备份终极指南:如何一键导出你的青春记忆

QQ空间数据备份终极指南:如何一键导出你的青春记忆 【免费下载链接】QZoneExport QQ空间导出助手,用于备份QQ空间的说说、日志、私密日记、相册、视频、留言板、QQ好友、收藏夹、分享、最近访客为文件,便于迁移与保存 项目地址: https://gi…

2026/10/20 19:04:30 阅读更多 →
仓库里堆的不是货,是真金白银 有色金属仓储:一个容错率为零的战场

仓库里堆的不是货,是真金白银 有色金属仓储:一个容错率为零的战场

有色金属仓储,和你在市面上看到的绝大多数仓库,有着本质区别。 这里放的,不是几块钱一瓶的饮料,不是几百块一件的衣服。是铜、是铝、是锌、是镍——每吨价格以万计,每垛货值动辄百万。 这不是仓库,这是一座…

2026/10/20 19:03:46 阅读更多 →
CD19靶向抗体药物偶联物能否改善复发难治性弥漫大B细胞淋巴瘤的临床结局?

CD19靶向抗体药物偶联物能否改善复发难治性弥漫大B细胞淋巴瘤的临床结局?

CD19靶向抗体药物偶联物能否改善复发难治性弥漫大B细胞淋巴瘤的临床结局?简述:抗体药物偶联物(ADC)通过将细胞毒药物精准递送至靶细胞,兼具高效与低脱靶毒性。Loncastuximab tesirine(Lonca)是一…

2026/10/18 8:14:01 阅读更多 →

最新新闻

基于改进鲸鱼算法的六自由度机械臂3-5-3多项式时间最优轨迹规划

基于改进鲸鱼算法的六自由度机械臂3-5-3多项式时间最优轨迹规划

机械臂的轨迹规划,说白了就是在“怎么走”和“走多快”之间做交易。生产线节拍压得紧,机械臂末端就得跑得更快,但速度一上来,关节的冲击和振动也跟着上来,时间久了螺丝都能给你抖松。我做过的一个很典型的项目——基于…

2026/10/20 19:04:03 阅读更多 →
SpringBoot+Vue民宿管理系统源码实战:从跑通到吃透

SpringBoot+Vue民宿管理系统源码实战:从跑通到吃透

这种基于SpringBootVue的民宿管理系统源码项目,这几年一直特别多,到2025年依然有不少人拿着类似标题的代码来找我帮忙跑通、改需求。原因不复杂:民宿短租业务贴近实际、模块边界清晰、技术栈覆盖面够广,作为课程设计、毕业设计或者…

2026/10/20 19:04:03 阅读更多 →
从传统CSS到Tailwind CSS:原子化开发实战心得与避坑指南

从传统CSS到Tailwind CSS:原子化开发实战心得与避坑指南

如果过去两年你一直在写前端,很难没听过 Tailwind CSS 这个名字。我第一次在真实项目里全面用它的时候,周围不少同事的第一反应是:这不就是把内联样式换了个写法?但真正用过大半年、把老项目也一个个迁过来之后,我发现…

2026/10/20 19:04:02 阅读更多 →
基于Django的图书推荐系统:标签画像与信息流反馈闭环实战

基于Django的图书推荐系统:标签画像与信息流反馈闭环实战

1. 为什么图书馆的找书体验,天然就是反人类的1.1 图书馆不是为"找书"设计的,它只是为"存书"设计的先说一个反直觉的观察:图书馆的物理空间和排架规则,本质上是为了"让管理员能精准定位一本书放在哪里&qu…

2026/10/20 19:04:02 阅读更多 →
UART红外接近感应免开发方案:一键学习与集成实战指南

UART红外接近感应免开发方案:一键学习与集成实战指南

做硬件集成的人应该都有这种体会:需求方丢过来一句“加个感应功能”,具体怎么实现、要改多少代码、会不会后期误触发,全都得自己扛。我最近给一个展示柜项目做改版,要求是“有人靠近柜门时,灯带和屏幕依次亮起来”。一…

2026/10/20 19:04:02 阅读更多 →
Playwright实战指南:从Selenium到下一代Web自动化

Playwright实战指南:从Selenium到下一代Web自动化

做Web自动化这些年,身边越来越多的人开始把Playwright当作首选,尤其是接触过旧的Selenium体系之后,再回头看Playwright,确实会有一句“原来早就该这样了”的感叹。写这篇文章的原因很简单,Playwright被称作“下一代Web…

2026/10/20 19:03:02 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →