数据结构:二叉搜索树(排序树)
1.二叉搜索树的定义
二叉搜索树要么是空树,要么是满足以下特性的树
(1)左子树不为空,那么左子树左右节点的值都小于根节点的值
(2)右子树不为空,那么右子树左右节点的值都大于根节点的值
(3)其所有子树也满足二叉搜索树性质
(4)二叉搜索树有两种形态,一种是支持插入冗余值,一种是不支持的(一般默认不支持冗余)
简单来说就是左边节点值 < 根节点值 < 右边节点值
二叉搜索树又叫二叉排序树,这是因为如果对他进行中序遍历,将会得到一组升序排序的数据
2.二叉搜索树的性能
二叉搜索树的搜索次数是等于树的高度的
最优情况:对于类似完全二叉树的树结构,时间复杂度可以达到O(logn)
最差情况:对于几乎所有数据都单侧分布的情况,时间复杂度会到O(n)
为了使他保持最优的性能,我们后续会引入平衡的概念,使他保持左右子树高度差小于等于1
3.部分实现非冗余二叉搜索树
节点基本结构搭建:
对于bstree的搭建:只需要加一个private的根节点指针即可
3.1插入
(1)若树为空,则直接新建节点,然后把新节点的地址给bs树的根节点,返回true,表示插入成功
(2)若树不为空,则判断key和当前节点的值的大小
若key小于当前节点的值:往左边搜索
若大于当前节点的值:往右边搜索
若等于当前节点值:直接返回false
如果我只用一个cur指针,是不能完成节点的链接的,因为链接节点的是cur的直接根节点,也就是prvcur节点,所以这里我们才创建一个prvnode指针,就是用于把新节点和bs树进行连接的。
(3)找到之后判断key于待链接节点的值的大小决定插入在左侧还是右侧
接下来进入测试阶段,不过在测试之前我们需要写一个中序遍历的方法,以便更直观的检查逻辑是否正确
我们利用递归的方式实现,结束条件是节点为空。
由于二叉搜索树左子树 < 根节点 < 右子树的性质,我们使用中序遍历可以实现升序输出
不过这里有个问题,我们需要传递bstree的private变量,可以使用友元,实现get函数等方法去获取m_root,现在我们介绍一个新的方式
封装进类中
我们在_inorder中实现具体功能,然后封装到inorder中,inorder主要用于调用m_root给_inorder传递参数
3.2查找
由于我们在插入部分已经进行过查找数据,所以我们只需要对insert的代码稍微改一下即可
下面我们进行调试
对1的查找成功,对11的查找失败,符合预期
3.3删除
对于删除,总共有四种情况
情况1:delete节点为叶子节点
解决方法:找到该节点后让他的父节点指向nullptr,并释放该节点空间
情况2:delete节点只有左节点
解决方法:让他的父节点指向他的那一侧指向delete的左节点
情况3:delete节点只有右节点
解决方法:让他的父节点指向他的那一侧指向delete的右节点
情况4:delete节点左右节点均有
![]()
解决方法:寻找delete左子树的最大节点,或者delete右子树的最小节点,然后交换delete位置的值与replace节点的值,让replace的父节点空余的一侧指向replace节点的左侧(从左子树找时),或者右侧(从右子树找时)。最后释放replace位置的空间
疑问一:为什么是寻找delete左子树的最大节点,或者delete右子树的最小节点?
答:
因为我们需要保持二叉搜索树的排序结构,只能从左树找一个最大数据(保证替换后根大于左树,且由于是从左树找的数据,必然也是小于右树的数据的),或者从右数找一个最小数据(和左树同理)
疑问二:寻找到的replace节点为什么可以直接让其父节点接入另一侧?
答:
因为replace已经是最左或者最右节点,所以不可能两侧都有节点,最多只有另一侧有节点。
特殊情况分析:
(1)对于delete节点有左右节点,且replace的节点就是左子树根节点,或右子树根节点
我们需要把replace的父节点设置为cur,而不是空,否则会有空指针访问。
并且replace父节点的指向侧也不是确定的,这种情况下和会更新replace父节点的情况,父节点的指向侧是相反的
(2)对于delete节点只有右节点或左节点,且delete节点为搜索树的根节点
由于这种基于情况1,2,3的情况下,我们需要释放delete节点的空间,所以根节点需要删除就涉及根节点的指针指向变更。
我们对cur==m_root的情况用if语句单独处理,让m_root指向cur->left或cur->right
代码实现:
(1)大框架搭建:我们使用insert的代码作为查找大框架
我们的代码写在找到delete节点cur的位置
(2)对情况1-3进行处理,并把特殊情况1纳入考虑
由于右侧为空/左侧为空的情况可以兼容两侧为空的情况,所以我们不用单独处理两侧为空的情况
(1)cur左为空
对于cur左为空且cur为根节点:更改m_root,指向cur有节点的一侧,也就是右侧
对于cur非根节点的情况:让父节点指向cur的那一侧指向cur有节点的一侧
(2)cur右为空
(3)cur左右非空
我们实现的是从左子树中查找最大节点,也可以换成从右子树查找最小节点
第一步:
查找replace节点:循环更改replace与replaceprv指针,直到replace指向的节点右侧为空
第二步:
交换delete与replace节点的值
第三步:让replace父节点指向replace节点的左侧
注意:
若replace父节点就是cur,说明节点就在cur的左侧,用父节点左侧指向replace节点左侧。
若replace父节点不为cur,说明进入了循环,而replace父节点就是上一次的replace,replace一直在往右走,所以其父节点一定是右侧指向replace节点
相关文章:

数据结构:二叉搜索树(排序树)
1.二叉搜索树的定义 二叉搜索树要么是空树,要么是满足以下特性的树 (1)左子树不为空,那么左子树左右节点的值都小于根节点的值 (2)右子树不为空,那么右子树左右节点的值都大于根节点的值 &#…...

【愚公系列】《Python网络爬虫从入门到精通》036-DataFrame日期数据处理
标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…...
C++(蓝桥杯常考点)
前言:这个是针对于蓝桥杯竞赛常考的C内容,容器这些等下棋期再讲 C 在DEVC中注释和取消注释的方法:ctrl/ ASCII值(常用的): A-Z:65-90 a-z:97-122 0-9:48-57 换行/n:10科学计数法:eg:…...

支付宝 IoT 设备入门宝典(下)设备经营篇
上篇介绍了支付宝 IoT 设备管理,但除了这些基础功能外,商户还可以利用设备进行一些运营动作,让设备更好的帮助自己,本篇就会以设备经营为中心,介绍常见的设备相关能力和问题解决方案。如果对上篇感兴趣,可以…...

蓝桥杯 之 填空题-位运算与循环
文章目录 循环握手问题门牌制作-循环小球反弹幸运数艺术与篮球跑步卡片 位运算3个1美丽的2024 位运算 可以关注这个Lowbit(x) 如何判断最低位是否是1? num&1 1就说明num最低位是1 循环 循环 握手问题 握手问题 思路分析: 可以直接计算出来&…...
iOS逆向工程概述与学习路线图
iOS逆向工程概述与学习路线图 欢迎各位加入我的iOS逆向工程专栏!在这个系列的第一篇文章中,我将为大家介绍iOS逆向工程的基本概念、应用场景以及完整的学习路线图,帮助大家建立清晰的学习框架。 什么是iOS逆向工程? 逆向工程&a…...

DeepSeek 助力 Vue3 开发:打造丝滑的时间选择器(Time Picker)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 DeepSeek 助力 Vue3 开发:打造丝滑的时间选择器(Time Picker)📚前言📚页面效果📚指令输入…...

基于 Ingress-Nginx 实现 mTLS 双向认证
目录 背景描述: TLS 和 MTLS 之间的差异 通过自签名证书启用双向 TLS 1. 生成证书 (1) 生成 CA(根证书颁发机构) (2) 生成 CA(根证书颁发机构) (3) 生成客户端证书 2. 在 Kubernetes 中配置 mTLS &#x…...

学到什么记什么(25.3.3)
Upload-labs 今日重新做了一下文件上传漏洞,这里第一题之前采用直接抓包改后缀名.jpg为.php,再写入一句话<?php phpinfo();?>然后放行,得到图片地址(可复制),本来直接访问图片地址即可得到敏感信息…...

【子网掩码计算器:Python + Tkinter 实现】
子网掩码计算器:Python Tkinter 实现 引言代码功能概述代码实现思路1. 界面设计2. 功能实现3. 事件处理 子网掩码计算器实现步骤1. 导入必要的库2. 定义主窗口类 SubnetCalculatorApp3. 创建菜单栏4. 创建界面组件5. 判断 IP 地址类别6. 计算子网信息7. 其他功能函…...
《解锁HarmonyOS NEXT高阶玩法:艺术图像识别功能开发全攻略》
在当今数字化时代,AI技术不断拓展其应用边界,为各行业带来前所未有的变革。在艺术领域,AI图像识别技术能够帮助艺术从业者、爱好者快速识别艺术品风格、作者,甚至挖掘艺术品背后的历史文化信息。本文将结合HarmonyOS NEXT API 12及…...
Spring Boot的启动流程
Spring Boot 的启动流程是一个复杂且有序的过程: 创建SpringApplication实例 — 调用run方法 — 启动完成(发布应用启动事件,配置环境,创建ApplicationContext,准备ApplicationContext,刷新ApplicationContext[【创建B…...

【通俗讲解电子电路】——从零开始理解生活中的电路(三)
实际应用案例:生活中的电子电路 ——拆解你身边的“隐形工程师” 1. 手电筒电路:最简单的直流系统 电路组成 电源:2节1.5V电池(串联3V)。 开关:按钮控制回路通断。 LED:发光二极管ÿ…...

TypeScript系列01-类型系统全解析
本文总结了 TypeScript 的类型系统基础,涵盖了: TypeScript 的价值:静态类型检查为 JavaScript 添加了类型安全保障基本类型系统:从原始类型到特殊类型(any、unknown、never)的完整介绍类型注解与推断&…...
ragflow-mysql 启动失败案例分析
一、问题描述 1.拉取RAGflow镜像失败 dependency failed to start: container ragflow-mysql is unhealthy2. 查询日志 docker logs ragflow-mysql显示 出现[rootlocalhost docker]# docker logs ragflow-mysql Fatal glibc error: CPU does not support x86-64-v2 Fatal …...
SslConnection::SslConnection()详解
一、🔍 SslConnection::SslConnection() 详解 这个构造函数的主要作用是: 创建 SSL 对象创建 BIO(I/O 缓冲区)初始化 SSL 服务器模式绑定回调函数(onRead() 处理接收数据) 📌 1. 初始化 SSL 相…...

unity lua属性绑定刷新
我们现在有一个 角色属性类叫heroModel,内容如下,当heroModel中的等级发生变化的时候,我们需要刷新界面显示等级信息,通常我们是在收到等级升级成功的协议的时候,发送一个事件,UI界面接受到这个事件的时候,刷新一下等级…...

Self-Pro: A Self-Prompt and Tuning Framework for Graph Neural Networks
Self-Pro: A Self-Prompt and Tuning Framework for Graph Neural Networks #paper/GFM/GNN-BASED# #paper/⭐⭐⭐# 注意:这篇文章是每个图一个GCN模型,而不是所有图一个GCN 模型 算是最早的涉及异配图的prompt了 贡献和动机: 非对…...
企业级-数据分类分级详细方案
一、方案背景 在数字化时代,数据成为企业和组织的核心资产。随着数据量的快速增长和数据应用场景的不断拓展,如何有效地管理和保护数据,确保数据的安全性、合规性和可用性,成为了亟待解决的问题。数据分类分级作为数据管理的基础工作,能够帮助企业清晰地了解自身的数据资…...

本地部署Qwen2.5-VL-7B-Instruct模型
本地部署Qwen2.5-VL-7B-Instruct模型 本地部署Permalink **创建环境** conda create -n qwenvl python3.11 -y# 报错: Solving environment: failedPackagesNotFoundError: The following packages are not available from current channels:# 处理: c…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...

基于小程序老人监护管理系统源码数据库文档
摘 要 近年来,随着我国人口老龄化问题日益严重,独居和居住养老机构的的老年人数量越来越多。而随着老年人数量的逐步增长,随之而来的是日益突出的老年人问题,尤其是老年人的健康问题,尤其是老年人产生健康问题后&…...
Spring事务传播机制有哪些?
导语: Spring事务传播机制是后端面试中的必考知识点,特别容易出现在“项目细节挖掘”阶段。面试官通过它来判断你是否真正理解事务控制的本质与异常传播机制。本文将从实战与源码角度出发,全面剖析Spring事务传播机制,帮助你答得有…...