news 2026/5/4 3:00:26

C++ | 二叉搜索树

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ | 二叉搜索树


🦌云深麋鹿

专栏:C++ | 用C语言学数据结构 | Java

回顾:上一篇我们结束了 多态,接下来这篇文章让我们进入到 二叉搜索树 的学习,体会新的设计思路吧~

放个目录

  • 一 概念
    • 性质
  • 二 性能分析
    • 2.1 二叉搜索树性能分析
    • 2.2 二分查找
  • 三 二叉搜索树的插入
    • 3.1 上代码
    • 3.2 测试
  • 四 二叉搜索树的查找
    • 4.1 上代码
    • 4.2 测试
  • 五 二叉搜索树的删除
    • 5.1 四种情况
    • 5.2 上代码
    • 5.3 测试
  • 六 二叉搜索树的其他实现
    • 6.1 析构函数
      • 6.1.1 _destory
      • 6.1.2 析构函数
      • 6.1.3 测试
    • 6.2 拷贝构造
      • 6.2.1 默认构造
      • 6.2.2 上代码
        • (1)辅助函数_constructor
        • (2)_constructor
      • 6.2.3 测试
    • 6.3 赋值重载
      • 6.3.1 代码
      • 6.3.2 测试
  • 七 二叉搜索树key和key/value使用场景
    • 7.1 key搜索场景
    • 7.2 key/value搜索场景

一 概念

二叉搜索树又称⼆叉排序树。

性质

  1. 若它的左子树不为空,则左子树上所有结点的值都小于等于根结点的值。
  2. 若它的右子树不为空,则右子树上所有结点的值都大于等于根结点的值。
  3. 它的左右子树也分别为⼆叉搜索树。
  4. ⼆叉搜索树中可以⽀持插入相等的值,也可以不⽀持插入相等的值,后续会提到具体实现。

二 性能分析

2.1 二叉搜索树性能分析

  1. 最优情况下,⼆叉搜索树为完全⼆叉树,其高度(即时间复杂度)为: logN。
  2. 最坏情况下,二叉搜索树为单枝,其高度(即时间复杂度)为: N。
  3. 总结:⼆叉搜索树增删查改时间复杂度为 O(N)

2.2 二分查找

二分查找时间复杂度为logN,但是有两大缺陷:

  1. 需要存储在支持下标随机访问的结构中,并且有序。
  2. 插入和删除数据效率很低(因为存储在下标随机访问的结构中,插入和删除数据⼀般需要挪动数据)。

三 二叉搜索树的插入

  1. 树为空。
  2. 树不为空,按⼆叉搜索树性质,插入值比当前结点大往右走,插入值比当前结点小往左走。
  3. 如果支持插入相等的值,插入值跟当前结点相等的值可以往右走,也可以往左走。

3.1 上代码

boolinsert(constK&key){if(!_root){_root=newNode(key);returntrue;}Node*parent=nullptr;Node*cur=_root;while(cur){if(cur->_key<key){parent=cur;cur=cur->_right;}elseif(cur->_key>key){parent=cur;cur=cur->_left;}else{returnfalse;}}cur=newNode(key);if(parent->_key>key){parent->_left=cur;}else{parent->_right=cur;}returntrue;}

当前不支持插入已出现过的值。

3.2 测试

wyzy::BSTree<int>tree;inta[]={8,3,1,10,6,4,7,14,13};for(autoe:a){tree.insert(e);}tree.inOrder();

运行:

四 二叉搜索树的查找

4.1 上代码

boolfind(constK&key){Node*cur=_root;while(cur){if(cur->_key<key){cur=cur->_right;}elseif(cur->_key>key){cur=cur->_left;}else{returntrue;}}returnfalse;}

跟插入类似的逻辑,只不过这里找到相等的就可以结束了。

4.2 测试

插入代码同上。

while(cin>>x){if(tree.find(x)){cout<<"find it"<<endl;}else{cout<<"not find it"<<endl;}}

运行:

测试涉及operator bool把iostream对象转换成bool值。

五 二叉搜索树的删除

5.1 四种情况

  1. 要删除结点N左右孩子均为空。
  2. 要删除的结点N左孩子为空,右孩子结点不为空。
  3. 要删除的结点N右孩子为空,左孩子结点不为空。
  4. 要删除的结点N左右孩子结点均不为空。

对应删除逻辑:

  1. 直接删除。
  2. 把右孩子交给父结点。
  3. 把左孩子交给父结点。
  4. 找 左子树的最大结点/右子树的最小结点 替代被删位置。

5.2 上代码

boolerase(constK&key){Node*parent=nullptr;Node*cur=_root;while(cur){if(cur->_key<key){parent=cur;cur=cur->_right;}elseif(cur->_key>key){parent=cur;cur=cur->_left;}else{break;}}if(cur){if(!cur->_left){if(!parent){_root=cur->_right;}elseif(cur==parent->_left){parent->_left=cur->_right;}else{parent->_right=cur->_right;}deletecur;}elseif(!cur->_right){if(!parent){_root=cur->_left;}elseif(cur==parent->_left){parent->_left=cur->_left;}else{parent->_right=cur->_left;}deletecur;}else{Node*mR_parent=cur;Node*minRight=cur->_right;while(minRight->_left){mR_parent=minRight;minRight=minRight->_left;}swap(cur->_key,minRight->_key);if(mR_parent==cur){mR_parent->_right=minRight->_right;}else{mR_parent->_left=minRight->_right;}deleteminRight;}returntrue;}returnfalse;}

5.3 测试

插入代码依旧。

for(autoe:a){tree.erase(e);tree.inOrder();}

运行:

六 二叉搜索树的其他实现

6.1 析构函数

6.1.1 _destory

需要有个递归函数我们另外写一个_destory:

void_destory(Node*root){if(!root){return;}_destory(root->_left);_destory(root->_right);deleteroot;}

6.1.2 析构函数

析构里调用_destory:

~BSTree(){_destory(_root);_root=nullptr;}

6.1.3 测试

依旧上面那棵树:

wyzy::BSTree<int>tree;inta[]={8,3,1,10,6,4,7,14,13};for(autoe:a){tree.insert(e);}

调试:

画出来这样:

调试:

6.2 拷贝构造

6.2.1 默认构造

这里需要显式定义默认构造。
走初始化列表:

BSTree(){}

或者强制默认生成:

BSTree()=default;

6.2.2 上代码

(1)辅助函数_constructor
void_constructor(Node*root){if(!root){return;}insert(root->_key);_constructor(root->_right);_constructor(root->_left);}

老生常谈的递归了。

(2)_constructor
BSTree(constBSTree&tree){_constructor(tree._root);}

6.2.3 测试

wyzy::BSTree<int>tree1;inta[]={8,3,1,10,6,4,7,14,13};for(autoe:a){tree1.insert(e);}wyzy::BSTree<int>tree2(tree1);tree1.inOrder();tree2.inOrder();

调试:

运行:

6.3 赋值重载

6.3.1 代码

复用。

BSTree&operator=(constBSTree&tree){if(tree._root!=nullptr){_destory(_root);_root=nullptr;}_constructor(tree._root);return*this;}

6.3.2 测试

wyzy::BSTree<int>tree1;wyzy::BSTree<int>tree2;inta[]={8,3,1,10,6,4,7,14,13};for(autoe:a){tree1.insert(e);}tree2=tree1;tree1.inOrder();tree2.inOrder();

调试:

运行:

七 二叉搜索树key和key/value使用场景

7.1 key搜索场景

  • 识别车牌号。

7.2 key/value搜索场景

  • 简单中英字典。
  • 商场停车场。
  • 统计文章单词出现次数。

二叉搜索树 的学习就到这里,下一篇我们上新的容器 map&set ,很快会更出来~


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/4 2:53:46

别再只用OneNote了!试试这款跨平台个人知识库神器Mybase,保姆级从安装到高阶玩法

别再只用OneNote了&#xff01;Mybase打造跨平台个人知识库的终极指南 在这个信息爆炸的时代&#xff0c;我们每天都在与海量的数字内容打交道——会议记录、项目文档、网页收藏、学习笔记...传统笔记软件如OneNote或印象笔记已经难以满足知识工作者对信息组织和检索的深度需求…

作者头像 李华
网站建设 2026/5/4 2:50:26

TensorFlow模型在NPU上的性能优化实战指南

1. 项目背景与核心价值在边缘计算和移动端AI应用爆发的当下&#xff0c;模型推理效率直接决定了产品体验的生死线。去年我们在部署某工业质检系统时&#xff0c;就曾因为TensorFlow模型在NPU上的性能不达标&#xff0c;导致产线节拍从每分钟120件暴跌到80件。这个惨痛教训促使我…

作者头像 李华
网站建设 2026/5/4 2:46:26

AI赋能可观测性:智能异常检测与根因分析实践

1. 项目概述&#xff1a;当AI遇上可观测性&#xff0c;BlazeUp-AI/Observal的诞生最近在搞一个挺有意思的项目&#xff0c;叫BlazeUp-AI/Observal。这个名字听起来有点拗口&#xff0c;但拆开来看就清晰了&#xff1a;BlazeUp-AI 和 Observal。简单来说&#xff0c;这是一个将人…

作者头像 李华
网站建设 2026/5/4 2:45:26

仿射变换无人地面车辆(ATUGV)设计与控制技术解析

1. 仿射变换无人地面车辆(ATUGV)概述在机器人技术快速发展的今天&#xff0c;传统无人地面车辆(UGV)的刚性结构限制了其在复杂环境中的适应性。我们团队开发了一种革命性的仿射变换无人地面车辆(ATUGV)&#xff0c;它通过创新的多体系统设计&#xff0c;实现了安全且高效的形态…

作者头像 李华
网站建设 2026/5/4 2:41:27

Cursor编辑器使用数据可视化:本地分析工具助你量化编码习惯

1. 项目概述与核心价值最近在深度使用Cursor编辑器进行开发时&#xff0c;我一直在思考一个问题&#xff1a;我每天花在代码编辑、调试、搜索上的时间分布究竟是怎样的&#xff1f;哪些文件是我高频访问的“热区”&#xff0c;哪些功能键被我按得最多&#xff1f;这种对自身工作…

作者头像 李华