二叉搜索树(图解)

文章目录

  • 二叉搜索树的概念
  • 插入
  • 查找
  • 二叉搜索树的删除操作
    • 删除单孩子和叶子节点。
    • `del`节点有两个孩子
      • 用左子树的最大节点替代
      • 用右子树的最小节点替代
  • 弊端

二叉搜索树的概念

对于每颗子树,左子树 < 根右子树 > 根

二叉搜索树有以下操作:

  • 插入
  • 删除
  • 查找

插入

插入很好理解,每次都要判断与当前位置的大小。

  • 如果小于当前位置就往当前节点的左边插入

  • 如果大于当前位置就往当前节点的右边插入。

等于的时候返回false,来表示插入失败。-> set的底层实现。 这个其实就是set的插入原理,所以我们的set才有去重的功能。

在这里插入图片描述

如上图,如果我们对现在的二叉搜索树进行中序遍历会得到什么呢?

  • 中序遍历结果: [2,3,6,8,9,10,11]

我们发现二叉搜索树的中序遍历就是一个有序序列。

代码实现:

bool insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* cur = _root;Node* parent = nullptr;while (cur){if (key < cur->_data){parent = cur;cur = cur->_left;}else if (key > cur->_data){parent = cur;cur = cur->_right;}else //如果遇到重复的返回false。return false;}cur = new Node(key);//判断新增节点连接在此时的哪边if (key < parent->_data)parent->_left = cur;elseparent->_right = cur;return true;}///测试
void Test_BSTRee()
{bit::BSTree<int> Myset;//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };for (auto e : a){Myset.insert(e);}Myset.inorder();
}int main()
{Test_BSTRee();return 0;
}

在这里插入图片描述

查找

Node* Find(const K& key){Node* cur = _root;while (cur){if (key < cur->_data){cur = cur->_left;}else if (key > cur->_data){cur = cur->_right;}elsereturn cur;}return nullptr;}

二叉搜索树的删除操作

删除主要分一下两种情况:

  • 单孩子和没有孩子节点。
  • del节点有两个孩子

删除单孩子和叶子节点。

在这里插入图片描述

我们可以发现,这两种情况可以合并为一种情况,我们以 del 表示要删除节点。

  • 首先判断我们的 delparent 的哪个孩子节点。

  • 只要 del 的左孩子为空,那么 parent 连接 del的右孩子指针。

  • 只要 del 的右孩子为空,那么 parent 连接 del的左孩子指针。

这里需要特殊处理我们删除根节点的情况

在这里插入图片描述

如果此时我们删除的节点是根节点,那么直接让根节点移动即可。

代码实现:

					//如果cur的左孩子为空   - 连接cur的右孩子if (cur->_left == nullptr){//特殊处理删除根节点的情况if (parent == nullptr){_root = _root->_right;}//判断cur为父节点的那个孩子else {if (parent->_left == cur)parent->_left = cur->_right;elseparent->_right = cur->_right;}delete cur;return true;}else if (cur->_right == nullptr)//如果cur的右孩子为空  - 连接cur的左孩子{//特殊处理删除根节点的情况if (parent == nullptr){_root = _root->_left;}else{//判断cur为父节点的哪个孩子if (parent->_left == cur)parent->_left = cur->_left;elseparent->_right = cur->_left;}delete cur;return true;}

del节点有两个孩子

当我们想要删除的节点左右孩子都有的时候,本质上是需要找到一个替代节点。这个节点要求:

  • 大于del左子树的所有节点 或者 小于del右子树的节点

符合要求的节点有两个: 1. 左子树的最大节点 2. 右子树的最小节点

用左子树的最大节点替代

  1. 左子树最大节点存在情况:

在这里插入图片描述

  1. 左子树最大节点不存在情况(右子树为空):

    在这里插入图片描述

    代码实现:

    			//以左孩子的最大节点作为替换节点Node* LeftMaxP = cur;Node* LeftMax = cur->_left;//找到最大节点while (LeftMax && LeftMax->_right){LeftMaxP = LeftMax;LeftMax = LeftMax->_right;}//把替换节点的值拷贝给del(删除)节点.cur->_data = LeftMax->_data;//删除此时的替换节点。//无论LeftMax是LeftMaxP的哪个孩子,都是连接LeftMax的左子树if (LeftMaxP->_right == LeftMax) {LeftMaxP->_right = LeftMax->_left;}else                            {LeftMaxP->_left = LeftMax->_left;}delete LeftMax;return true;
    

用右子树的最小节点替代

这里也分为两种情况:

  1. 右子树最小节点存在

在这里插入图片描述

  1. 右子树最小节点不存在

    在这里插入图片描述

代码实现:

						//以右孩子的最小节点作为替换节点Node* RightMinP = cur;Node* RightMin = cur->_right;//找到右子树的最小节点while (RightMin && RightMin->_left){RightMinP = RightMin;RightMin = RightMin->_left;}//把替换节点的值拷贝给del(删除)节点.cur->_data = RightMin->_data;//删除此时的替换节点。if (RightMinP->_right == RightMin){RightMinP->_right = RightMin->_right;}else                            {RightMinP->_left = RightMin->_right;}delete RightMin;return true;

弊端

平常状态小,我们二叉搜索树的查找效率是 l o g 2 N log_2{N} log2N 的,但是如果我们的元素是有序的那么,此时二叉树就会退化为单叉链,查找效率为 O ( N ) O(N) O(N)。类似这样:

在这里插入图片描述

所以后面就引出了AVL树和红黑树,他们俩都是可以通过旋转来是高度平衡。

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

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

相关文章

代码随想录二刷(哈希表)

代码随想录二刷(哈希表) 三数之和思路反正对于我来说是真的难想出来。 若这道题还是采用哈希表的思路去做&#xff0c;非常麻烦&#xff0c;并且还要考虑去重的操作。所以这道题其实用双指针&#xff0c;是更方便的。 具体程序如下&#xff1a; class Solution:def threeSu…

Docker简介和Docker常见命令

目录 1. Docker 简介 1.1 Docker 的核心概念 1.2 Docker 的优势 1.3 Docker 工作流程 2. 常见命令 2.1 基本命令 2.2 镜像操作 2.3 容器操作 2.4 网络操作 2.5 卷操作 2.6 日志和监控 2.7 清理命令 3. 注意事项和最佳实践 3.1 镜像操作 3.2 容器操作 3.3 网络操…

2.1、matlab绘图汇总(图例、标题、坐标轴、线条格式、颜色和散点格式设置)

1、前言 在 MATLAB 中进行绘图是一种非常常见且实用的操作,可以用来可视化数据、结果展示、分析趋势等。通过 MATLAB 的绘图功能,用户可以创建各种类型的图形,包括线图、散点图、柱状图、曲线图等,以及三维图形、动画等复杂的可视化效果。 在绘图之前,通常需要先准备好要…

docker部署容器端口占用问题

docker部署容器端口占用问题 当我在使用 Windows 下使用 Docker Desktop 部署docker容器时经常性发生容器启动失败的提示&#xff0c;并且有的时候重启电脑后就能成功启动容器&#xff0c;这是因为 Hyper-V 引起的 保留端口&#xff0c;这部分端口将会被系统保留&#xff0c;无…

基于SpringBoot+Vue的企业客户信息反馈平台(带1w+文档)

基于SpringBootVue的企业客户信息反馈平台(带1w文档) 基于SpringBootVue的企业客户信息反馈平台(带1w文档) 企业客户信息反馈平台的开发运用java技术&#xff0c;MIS的总体思想&#xff0c;以及MYSQL等技术的支持下共同完成了该平台的开发&#xff0c;实现了企业客户信息反馈管…

【C++】哈希容器

unordered系列关联式容器 在之前的博文中介绍过关联式容器中的map与set&#xff0c;同map与set一样&#xff0c;unordered_set与unordered_set也是关联式容器。 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;查询效率可以达到logN&#xff1b;在…

安装 Terraform for Tencent 使用

第一步 &#xff1a;下载安装包 前往 Terraform 官网&#xff0c;使用命令行直接安装 Terraform 或下载二进制安装文件。 解压并配置全局路径 Linux/MAC&#xff1a;export PATH$PATH:${可执行文件所在目录} 例如&#xff1a;export PATH$PATH:$/usr/bin/terraform Win…

vue2学习 -- 核心语法

文章目录 前置简介1. 模板语法2. 数据2.1 数据绑定2.2 el与data的两种写法2.3 MVVM模型2.4 Object.defineProperty2.5 Vue中的数据代理 3. 事件3.1 事件处理3.2 事件修饰符3.3 键盘事件 4. 计算属性5. 监视(侦听)属性5.1 书写形式5.2 深度监视5.3 简写形式5.4 计算属性和监听属…

Go语言生成excel、将excel保存到本地、将多个excel表格压缩为压缩包、在压缩文件上传OSS删除本地excel文件和压缩包

最近在公司了个需求&#xff0c;主要涉及到文件导出&#xff0c;需要根据特定表格文件生成excel文件导出&#xff0c;同时对导出的excel临时保存本地&#xff0c;生成压缩包&#xff0c;将压缩包上传至OSS&#xff08;Object Storage Service&#xff09;后删除本地临时文件。下…

Go+Redis零基础到用户管理系统API实战_20240730 课程笔记

概述 如果您没有Golang的基础&#xff0c;应该学习如下前置课程。 Golang零基础入门Golang面向对象编程Go Web 基础Go语言开发REST API接口_20240728Go语言操作MySQL开发用户管理系统API教程_20240729Redis零基础快速入门_20231227 基础不好的同学每节课的代码最好配合视频进…

AI绘画模型之:VAE、SD 与 SD-XL

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

Linux常用工具

文章目录 tar打包命令详解unzip命令&#xff1a;解压zip文件vim操作详解netstat详解df命令详解ps命令详解find命令详解 tar打包命令详解 tar命令做打包操作 当 tar 命令用于打包操作时&#xff0c;该命令的基本格式为&#xff1a; tar [选项] 源文件或目录此命令常用的选项及…

19082 中位特征值

这个问题可以通过深度优先搜索&#xff08;DFS&#xff09;和优先队列来解决。我们首先使用DFS来计算每个节点的特征值&#xff0c;然后我们将所有节点的特征值放入一个优先队列中&#xff0c;然后我们从优先队列中取出中间的元素&#xff0c;这就是我们要找的中位数。 以下是…

如何选择合适的自动化测试工具!

选择合适的自动化测试工具是一个涉及多方面因素的决策过程。以下是一些关键步骤和考虑因素&#xff0c;帮助您做出明智的选择&#xff1a; 一、明确测试需求和目标 测试范围&#xff1a;确定需要自动化的测试类型&#xff08;如单元测试、集成测试、UI测试等&#xff09;和测试…

React-Native 宝藏库大揭秘:精选开源项目与实战代码解析

1. 引言 1.1 React-Native 简介 React-Native 是由 Facebook 开发的一个开源框架&#xff0c;它允许开发者使用 JavaScript 和 React 的编程模型来构建跨平台的移动应用。React-Native 的核心理念是“Learn Once, Write Anywhere”&#xff0c;即学习一次 React 的编程模型&am…

社区养老服务小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;服务人员管理&#xff0c;服务产品管理&#xff0c;服务预约管理&#xff0c;服务状态管理&#xff0c;服务退订管理&#xff0c;活动管理&#xff0c;视频管理 微信端账号功能包…

基于cubeMX的STM32的RTC实时时钟实现

1、在仪器仪表的项目开发中&#xff0c;时常需要设备显示当前的日期和时间&#xff0c;这时&#xff0c;可以使用STM32自带的RTC实时时钟模块来实现此功能。这里我们使用STM32F103RCT6单片机芯片为例。 2、cubeMX的设置 &#xff08;1&#xff09;RTC设置 &#xff08;2&…

民大食堂用餐小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;商家管理&#xff0c;档口号管理&#xff0c;商家餐品管理&#xff0c;餐品种类管理&#xff0c;购物车管理&#xff0c;订单信息管理 微信端账号功能包括&#xff1a;系统首页&a…

yolov10来了!用yolov10训练自己的数据集(原理、训练、部署、应用)

一、引言 YOLOv9还没热乎呢&#xff0c;YOLOv10就出来了&#xff0c;太卷了&#xff01;太快了&#xff01; 自今年2月YOLOv9发布之后&#xff0c; YOLO&#xff08;You Only Look Once&#xff09; 系列的接力棒传到了清华大学研究人员的手上。YOLOv10推出的消息引发了AI界的…

使用 Postman 进行 Trello API 自动化测试的完整指南

文章目录 前言一、自动化测试是什么&#xff1f;二、比较自动化测试与手工测试1. 自动化测试2. 手工测试 三、环境搭建1.创建Collection2.创建环境变量3.添加API请求 四、设计测试用例1. API简单调用2. 获取所有emoji3. 创建一个新看板&#xff1a;4. 获得创建的看板信息5. 在看…