C++ --- 二叉搜索树

1 二叉搜索树的概念

⼆叉搜索树⼜称⼆叉排序树,它或者是⼀棵空树,或者是具有以下性质的⼆叉树:

1 若它的左⼦树不为空,则左⼦树上所有结点的值都⼩于等于根结点的值

2 若它的右⼦树不为空,则右⼦树上所有结点的值都⼤于等于根结点的值

3 它的左右⼦树也分别为⼆叉搜索树

4 ⼆叉搜索树中可以⽀持插⼊相等的值,也可以不⽀持插⼊相等的值,具体看使⽤场景定义

2 二叉搜索树的性能分析 

最优情况下,⼆叉搜索树为完全⼆叉树(或者接近完全⼆叉树),其⾼度为: logN

最差情况下,⼆叉搜索树退化为单⽀树(或者类似单⽀),其⾼度为: N

所以综合⽽⾔⼆叉搜索树增删查改时间复杂度为: O(N)

那么这样的效率显然是⽆法满⾜我们需求的,我们后续课程需要继续讲解⼆叉搜索树的变形,平衡⼆叉搜索树AVL树和红⿊树,才能适⽤于我们在内存中存储和搜索数据。

另外需要说明的是,⼆分查找也可以实现 O(logN) 2 级别的查找效率,但是⼆分查找有两⼤缺陷:

1. 需要存储在⽀持下标随机访问的结构中,并且有序。

2. 插⼊和删除数据效率很低,因为存储在下标随机访问的结构中,插⼊和删除数据⼀般需要挪动数据。

这⾥也就体现出了平衡⼆叉搜索树的价值

 3 二叉搜索树的插入

 插⼊的具体过程如下:

1. 树为空,则直接新增结点,赋值给root指针

2. 树不空,按⼆叉搜索树性质,插⼊值⽐当前结点⼤往右⾛,插⼊值⽐当前结点⼩往左⾛,找到空位 置,插⼊新结点。

3. 如果⽀持插⼊相等的值,插⼊值跟当前结点相等的值可以往右⾛,也可以往左⾛,找到空位置,插⼊新结点。(要注意的是要保持逻辑⼀致性,插⼊相等的值不要⼀会往右⾛,⼀会往左⾛)

        代码实现:

bool Insert(const K& key)
{if (_root == nullptr){_root = new Node(key);return true;}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{return false;}}cur = new Node(key);if (key > parent->_key){parent->_right = cur;}else{parent->_left = cur;}return true;
}

4 二叉搜索树的查找 

1.从根开始⽐较,查找x,x⽐根的值⼤则往右边⾛查找,x⽐根值⼩则往左边⾛查找。

2. 最多查找⾼度次,⾛到到空,还没找到,这个值不存在。

3. 如果不⽀持插⼊相等的值,找到x即可返回

4. 如果⽀持插⼊相等的值,意味着有多个x存在,⼀般要求查找中序的第⼀个x。如下图,查找3,要 找到1的右孩⼦的那个3返回

        代码实现:

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

5 二叉搜索树的删除 

 ⾸先查找元素是否在⼆叉搜索树中,如果不存在,则返回false。

如果查找元素存在则分以下四种情况分别处理:(假设要删除的结点为N)

1. 要删除结点N左右孩⼦均为空

2. 要删除的结点N左孩⼦位空,右孩⼦结点不为空

3. 要删除的结点N右孩⼦位空,左孩⼦结点不为空

4. 要删除的结点N左右孩⼦结点均不为空

对应以上四种情况的解决⽅案:

1. 把N结点的⽗亲对应孩⼦指针指向空,直接删除N结点(情况1可以当成2或者3处理,效果是⼀样 的)

2. 把N结点的⽗亲对应孩⼦指针指向N的右孩⼦,直接删除N结点

3. 把N结点的⽗亲对应孩⼦指针指向N的左孩⼦,直接删除N结点

4. ⽆法直接删除N结点,因为N的两个孩⼦⽆处安放,只能⽤替换法删除。找N左⼦树的值最⼤结点 R(最右结点)或者N右⼦树的值最⼩结点R(最左结点)替代N,因为这两个结点中任意⼀个,放到N的 位置,都满⾜⼆叉搜索树的规则。替代N的意思就是N和R的两个结点的值交换,转⽽变成删除R结 点,R结点符合情况2或情况3,可以直接删除。

代码实现:

bool Erase(const K& key)
{Node* cur = _root;Node* parent = nullptr;while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}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 = _root->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;}else{Node* replaceParent = cur;Node* replace = cur->_right;while (replace->_left){replaceParent = replace;replace = replace->_left;}swap(cur->_key, replace->_key);if (replaceParent->_left == replace)replaceParent->_left = replace->_right;elsereplaceParent->_right = replace->_right;delete replace;}return true;}}return false;
}

 二叉树的遍历

那么上面写完了我们总得是要测试一下的,那么为了输出的结果好看,二叉搜索树的中序遍历就可以将输出的结果按照升序的样式打印出来。

        代码实现: 

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

在这里是因为,在外部调用InOrder的话,root并不作为public对象对外可以进行访问的,因此单纯的写一个InOrder函数达不到打印的效果,但是可以在创建一个无参的InOrder来进行调用,这样内部的函数进行调用就不会出现那种情况了,那么就可以达到我们想要的效果了。

 到这里关于二叉搜索树的介绍就到这里了,感谢你的观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/74623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跨语言语言模型预训练

摘要 最近的研究表明&#xff0c;生成式预训练在英语自然语言理解任务中表现出较高的效率。在本研究中&#xff0c;我们将这一方法扩展到多种语言&#xff0c;并展示跨语言预训练的有效性。我们提出了两种学习跨语言语言模型&#xff08;XLM&#xff09;的方法&#xff1a;一种…

文件描述符,它在哪里存的,exec()后还存在吗

学过计系肯定了解 寄存器、程序计数器、堆栈这些 程序运行需要的资源。 这些是进程地址空间。 而操作系统分配一个进程资源时&#xff0c;分配的是 PCB 进程控制块。 所以进程控制块还维护其他资源——程序与外部交互的资源——文件、管道、套接字。 文章目录 文件描述符进程管…

Slidev使用(一)安装

文章目录 1. **安装位置**2. **使用方式**3. **适用场景**4. **管理和维护** 全局安装1. **检查 Node.js 和 npm 是否已安装**2. **全局安装 Slidev CLI**3. **验证安装是否成功**4. **创建幻灯片文件**5. **启动 Slidev**6. **实时编辑和预览**7. **构建和导出&#xff08;可选…

第二十一章:模板与继承_《C++ Templates》notes

模板与继承 重点和难点编译与测试说明第一部分&#xff1a;多选题 (10题)第二部分&#xff1a;设计题 (5题)答案与详解多选题答案&#xff1a;设计题参考答案 测试说明 重点和难点 21.1 空基类优化&#xff08;EBCO&#xff09; 知识点 空基类优化&#xff08;Empty Base Cla…

AOA与TOA混合定位,MATLAB例程,自适应基站数量,三维空间下的运动轨迹,滤波使用EKF

本代码实现了一个基于 到达角(AOA) 和 到达时间(TOA) 的混合定位算法,结合 扩展卡尔曼滤波(EKF) 对三维运动目标的轨迹进行滤波优化。代码通过模拟动态目标与基站网络,展示了从信号测量、定位解算到轨迹滤波的全流程,适用于城市峡谷、室内等复杂环境下的定位研究。 文…

量子计算:开启未来计算的新纪元

一、引言 在当今数字化时代&#xff0c;计算技术的飞速发展深刻地改变了我们的生活和工作方式。从传统的电子计算机到如今的高性能超级计算机&#xff0c;人类在计算能力上取得了巨大的进步。然而&#xff0c;随着科技的不断推进&#xff0c;我们面临着越来越多的复杂问题&…

AMD机密计算虚拟机介绍

一、什么机密计算虚拟机 机密计算虚拟机 是一种基于硬件安全技术(如 AMD Secure Encrypted Virtualization, SEV)的虚拟化环境,旨在保护虚拟机(VM)的 ​运行中数据​(包括内存、CPU 寄存器等)免受外部攻击或未经授权的访问,即使云服务提供商或管理员也无法窥探。 AMD …

如何通过数据可视化提升管理效率

通过数据可视化提升管理效率的核心方法包括清晰展示关键指标、及时发现和解决问题、支持决策优化。其中&#xff0c;清晰展示关键指标尤为重要。通过数据可视化工具直观地呈现关键绩效指标&#xff08;KPI&#xff09;&#xff0c;管理者能快速、准确地理解业务现状&#xff0c…

.git 文件夹

文件夹介绍 &#x1f34e; 在 macOS 上如何查看 .git 文件夹&#xff1f; ✅ 方法一&#xff1a;终端查看&#xff08;最推荐&#xff09; cd /你的项目路径/ ls -a-a 参数表示“显示所有文件&#xff08;包括隐藏的&#xff09;”&#xff0c;你就能看到&#xff1a; .git…

MongoDB 与 Elasticsearch 使用场景区别及示例

一、核心定位差异 ‌MongoDB‌ ‌定位‌&#xff1a;通用型文档数据库&#xff0c;侧重数据的存储、事务管理及结构化查询&#xff0c;支持 ACID 事务‌。‌典型场景‌&#xff1a; 动态数据结构存储&#xff08;如用户信息、商品详情&#xff09;‌。需事务支持的场景&#xf…

【深度学习基础 2】 PyTorch 框架

目录 一、 PyTorch 简介 二、安装 PyTorch 三、PyTorch 常用函数和操作 3.1 创建张量&#xff08;Tensor&#xff09; 3.2 基本数学运算 3.3 自动求导&#xff08;Autograd&#xff09; 3.4 定义神经网络模型 3.5 训练与评估模型 3.6 使用模型进行预测 四、注意事项 …

uniapp中APP上传文件

uniapp提供了uni.chooseImage&#xff08;选择图片&#xff09;&#xff0c; uni.chooseVideo&#xff08;选择视频&#xff09;这两个api&#xff0c;但是对于打包成APP的话就没有上传文件的api了。因此我采用了plus.android中的方式来打开手机的文件管理从而上传文件。 下面…

推陈换新系列————java8新特性(编程语言的文艺复兴)

文章目录 前言一、新特性秘籍二、Lambda表达式2.1 语法2.2 函数式接口2.3 内置函数式接口2.4 方法引用和构造器引用 三、Stream API3.1 基本概念3.2 实战3.3 优势 四、新的日期时间API4.1 核心概念与设计原则4.2 核心类详解4.2.1 LocalDate&#xff08;本地日期&#xff09;4.2…

树莓派5从零开发至脱机脚本运行教程——1.系统部署篇

树莓派5应用实例——工创视觉 前言 哈喽&#xff0c;各位小伙伴&#xff0c;大家好。最近接触了树莓派&#xff0c;然后简单的应用了一下&#xff0c;学习程度并不是很深&#xff0c;不过足够刚入手树莓派5的小伙伴们了解了解。后面的几篇更新的文章都是关于开发树莓派5的内容…

GPT Researcher 的win docker安装攻略

github网址是&#xff1a;https://github.com/assafelovic/gpt-researcher 因为docker安装方法不够清晰&#xff0c;因此写一个使用方法 以下是针对 Windows 系统 使用 Docker 运行 AI-Researcher 项目的 详细分步指南&#xff1a; 步骤 1&#xff1a;安装 Docker 下载 Docke…

【后端】【Django DRF】从零实现RBAC 权限管理系统

Django DRF 实现 RBAC 权限管理系统 在 Web 应用中&#xff0c;权限管理 是一个核心功能&#xff0c;尤其是在多用户系统中&#xff0c;需要精细化控制不同用户的访问权限。本文介绍如何使用 Django DRF 设计并实现 RBAC&#xff08;基于角色的访问控制&#xff09;系统&…

C#基础学习(五)函数中的ref和out

1. 引言&#xff1a;为什么需要ref和out&#xff1f; ​问题背景&#xff1a;函数参数默认按值传递&#xff0c;值类型在函数内修改不影响外部变量&#xff1b;引用类型重新赋值时外部对象不变。​核心作用&#xff1a;允许函数内部修改外部变量的值&#xff0c;实现“双向传参…

八纲辨证总则

一、八纲辨证的核心定义 八纲即阴、阳、表、里、寒、热、虚、实&#xff0c;是中医分析疾病共性的纲领性辨证方法。 作用&#xff1a;通过八类证候归纳疾病本质&#xff0c;为所有辨证方法&#xff08;如脏腑辨证、六经辨证&#xff09;的基础。 二、八纲分类与对应关系 1. 总…

【linux重设gitee账号密码 克隆私有仓库报错】

出现问题时 Cloning into xxx... remote: [session-1f4b16a4] Unauthorized fatal: Authentication failed for https://gitee.com/xxx/xxx.git/解决方案 先打开~/.git-credentials vim ~/.git-credentials或者创建一个 torch ~/.git-credentials 添加授权信息 username/pa…

绿联NAS安装内网穿透实现无公网IP也能用手机平板远程访问经验分享

文章目录 前言1. 开启ssh服务2. ssh连接3. 安装cpolar内网穿透4. 配置绿联NAS公网地址 前言 大家好&#xff0c;今天给大家带来一个超级炫酷的技能——如何在绿联NAS上快速安装cpolar内网穿透工具。想象一下&#xff0c;即使没有公网IP&#xff0c;你也能随时随地远程访问自己…