《java数据结构》--一篇解决二叉搜索树!!

😸二叉搜索树的概念

二叉搜索树又名二叉排序树,一般具有以下性质:

  1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  3. 它的左右子树也分别为二叉搜索树

将其具现为一个图就是这样 

🐭二叉搜索树的查找

我们可以根据二叉搜索树的特性,它的每一个结点的左子树比根小右子树比根大来进行快速查找,当一个数比根结点小就往根结点的左边找,比根结点大就往右边找,每次都可以将搜索范围缩小一半,最多查找h(树的高度)次,一个相对平衡的二叉树搜索树的时间复杂度大概为O(logN),为什么要说相对平衡呢?🤔因为在极端情况下,假如一棵二叉树只有右子树,那么他就会变成一个链表,这时他的复杂度就会变成O(logN)。所以在实际使用中,要注意维护二叉搜索树的平衡性(形状),因此在二叉搜索树的基础上,就诞生出了一些更具平衡性的树如,红黑树,AVL树。

🐭二叉搜索树的排序

因为二叉搜索树的每一棵子树都满足左子树 < 根 < 右子树,所以我们可以进行中序遍历,这样就可以得到一个升序序列了,一个相对平衡的二叉树搜索树的时间复杂度大概为O(NlogN)

😸二叉搜索树的实现

🐱二叉搜索树的创建

具体方法和创建一棵二叉树一样,每棵树都要有左右子树,然后创建一个初始的根结点

🐱二叉搜索树的查找

为了方便我们先写一个判空方法😋

🐭思路:

  1. 从根节点开始一直向下遍历
  2. 当目标值大于当前结点的值,就往右子树中继续搜索
  3. 当目标值小于当前结点的值,就往左子树中继续搜索
  4. 当目标值刚好等于当前结点值,直接返回true表示已经找到
  5. 当遍历到最后依然每找到则返回false表示没找到

这里我来画图举个例子:

🐱二叉搜索树的插入

🐭思路:

二叉搜索树的插入只能插到叶子结点上,而且不能插入相同的结点

首先需要先判断树是否为空

树为空:

😊即根结点为空,直接插入就行

树不为空:

😊因为二叉树不像链表,直接遍历到最后一个结点然后将新结点连在最后一个结点的后就行,二叉搜索树可能要插在左边还可能插在右边,所以不能像链表那样直接cur.next != null找到最后一个结点,我们要先定义一个父节点,用来标记要插到的叶子结点的父节点,先找到这个父节点然后在判断,要插入的值和这个父节点的大小以判断是插在左边还是右边。

🐱🐱二叉搜素树的删除(难点)

🐭思路:

首先我们要先找到要删除的结点,并且还有记住他的父节点,方法和刚刚写的插入类似,大的往右找小的往左找,当找到后对结点进行删除,那么要怎么删除呢🧐?因为比较复杂,需要单独写一个方法😋。

//parent是待删除的结点的父结点,cur是要删除的结点

因为这是一个二叉树删除之后不能破坏它的结构所以不能像线性表那样直接删除,要分几种情况:

🐭要删除的结点左边为空cur.left==null

1.cur是根结点,则直接让root = cur.right

要删除的结点左边为空,并且是根结点所以直接让根结点等于其右子树就行

2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.right

如图,因为要删除的结点没有左子树,并且是父节点的左子树,所以直接让父节点的左边连上cur的右边

3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.right

和上一个类似,因为要删除的结点没有左子树,并且是父节点的右子树,所以直接让父节点的右边连上cur的右边

🐭要删除的结点右边为空cur.right == null

1. cur 是 root,则 root = cur.left

因为要删除的结点右边为空,并且是根结点所以直接让根结点等于根结点的左子树

2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.left

因为cur是父节点的左边,并且cur没有右子树,所以直接让父节点的左边,连cur的左边

3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.left

因为cur是父节点的右边,并且没有右子树,所以直接让父节点的右边连cur的左边

🐭要删除的结点左右都为空cur.left != null && cur.right != null

这种情况利用上面的方法依然可以实现,比如cur在父节点的右边,因为cur没有子树,所以不管父节点连cur的左边还是右边(左右都为null)都可以完成删除,cue在父节点左边也是一样的,所以这部分内容利用上面的代码也能实现

以上我们讨论的是要删除的结点右空的子树的情况,那么接下来我们要讨论没有子树的情况即

🐭要删除的结点左右都不为空

当cur左右结点都不为空时就会比较麻烦,我们的老招式就不管用了😣😟比如这样:

这该让父节点怎么连?🤔好像不管怎么连都会破坏树的结构🧐那么索性就不连了,因为当树的结构比较复杂时这样很容易就会破坏树的结构,那么就不删了吗🧐当然不是,只是用的方法不是删除,而是替代。如果我用一个合适的数去把我要删除的这个数给替代掉,然后再将这个数原来所在的结点删除,不就间接的完成了删除而且不会破坏树的结构了吗😉,用的这个方法也可以叫做寻找替罪羊。

思路:

既然我们在替代后,还要删除掉原来结点那么我们找的替罪羊(用来覆盖cur的结点)必须容易删除要不然就没有意义,所以替罪羊至少具有两点,1结点左右子树必须有空的2大小必须合适,要满足二叉搜索树左边比结点小右边比结点大的特性

左右子树必有空,只需要向下查找总能找到,那么我们现在要思考的是怎么找到大小合适的结点?

根据二叉搜索树的的特性我们有两种方法可以找到

  • 在cur的左边找最大值
  • 在cur的右边找最小值

这里我就使用在cur的右边找最小值来演示,因为cur的右子树都是比cur大的数,所以我们就要在其右子树中找到比cur.right小的数就行,那么只需要找cur.right的左子树不就好了😉,既比cur大(因为在cur右边),又比cur.right小(因为在cur左边)

所以根据上面的分析我们知道了我们要找的结点是cur.right的左子树,并且这个替罪羊结点有空的子树,如果能找到,这个空的结点必然是左子树(如果左子树还有结点证明还可以向下查找)最后用这个结点覆盖掉cur,再删掉就行😉

//在cur的左边找最大值,同理找cur.left的右子树如果能找到,他的右子树必然是空的

//如果替罪羊结点就是cur.right就不能再往左边找了,因为这时左边已经为空了,所以要单独判断一下

😸性能分析

二叉搜索树插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。 对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度 的函数,即结点越深,则比较次数越多。

最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:logN

最差情况下,二叉搜索树退化为单支树,其平均比较次数为:N/2

🐭到这里我们就聊完了二叉搜索树,如果你有什么不懂或者其他见解欢迎在下方评论或者私信博主,也可以希望多多支持一下博主!!!🥰🥰,我们下一个篇章聊一聊java中的map和set😸

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

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

相关文章

61. UE5 RPG 实现敌人近战攻击技能和转向攻击

在前面&#xff0c;我们实现了敌人的AI系统&#xff0c;敌人可以根据自身的职业进行匹配对应的攻击方式。比如近战战士会靠近目标后进行攻击然后躲避目标的攻击接着进行攻击。我们实现了敌人的AI行为&#xff0c;但是现在还没有实现需要释放的技能&#xff0c;接下来&#xff0…

通过定时器和脉冲控制LED

目录 一、定时器 &#xff08;一&#xff09;定时器简介 &#xff08;二&#xff09;定时器类型 1、常见定时器 2、定时器的主要功能 3、常规定时器 &#xff08;三&#xff09;定时器配置 1、定时器标准外设库接口函数 2、定时器标准外设库配置 二、PWM &#xff08…

匿名函数(lambda)

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 匿名函数是指没有名字的函数&#xff0c;应用在需要一个函数&#xff0c;但是又不想费神去命名这个函数的场合。通常情况下&#xff0c;这样的函数只…

【Qt】Qt界面美化指南:深入理解QSS样式表的应用与实践

文章目录 前言&#xff1a;1. 背景介绍2. 基本语法3. QSS 设置方式3.1. 设置全局样式3.2. 从文件加载样式表3.3. 使用 Qt Designer 编辑样式 总结&#xff1a; 前言&#xff1a; 在当今这个视觉至上的时代&#xff0c;用户界面&#xff08;UI&#xff09;的设计对于任何软件产…

智能制造案例专题|与MongoDB一起解锁工业4.0转型与增长的无限潜力!

MongoDB 智能制造 数字化技术的洪流在各个产业链的主干和枝节涌现。在工业制造领域&#xff0c;能否通过数字化技术实现各生产要素、生产环节之间的紧密配合&#xff0c;高效规划、管理整个生产流程&#xff0c;是企业提升韧性、赢得竞争的关键。随着工业4.0的深入发展和智能…

高级Java开发者的自我修养:深入剖析JVM垃圾回收机制及面试要点

在探索Java虚拟机&#xff08;JVM&#xff09;的奥秘过程中&#xff0c;垃圾回收机制&#xff08;GC&#xff09;是一个不可或缺的话题&#xff0c;尤其在面对大型应用和系统优化时显得尤为重要。JVM的自动内存管理是Java编程语言中一项革命性的特性&#xff0c;它大大简化了程…

AI盒子在智慧加油站的应用

方案背景 为规范加油站作业&#xff0c;保障人民生命财产安全&#xff0c;《加油站作业安全规范》&#xff08;AQ 3010-2007&#xff09;中第五条规定&#xff1a;卸油作业基本要求&#xff0c;明确防静电、防雷电、防火、人员值守、禁止其他车辆及非工作人员进入卸油区。 痛点…

RocketMQ学习(2) 深入学习

RokcetMQ的介绍和基础知识见这篇博客——RocketMQ学习(1) 快速入门 本篇为上一篇的深入学习&#xff0c;很多基础知识不再赘述。 目录 消息重复消费问题(去重;幂等)布隆过滤器 重试机制死信消息 SpringBoot集成RocketMQ集成SpringBoot发送不同消息模式(同步消息)异步消息单向消…

使用el-tab,el-tab-pane循环使用循环后不显示下划线问题

在vue项目中使用element-UI el-tab里的el-tab-pane是循环出来的&#xff0c;但是循环出来后选中tab不显示下划线了 文章目录 问题问题展示效果问题代码问题原因 解决方案解决后效果解决方案1代码 解决方案2代码 问题 问题展示效果 问题代码 <el-tabs v-model"activeNa…

音量的对数表示与浮点数表示

音量用浮点数&#xff08;float&#xff09;和对数&#xff08;logarithmic scale&#xff09;表示各有特点和应用场景 浮点数&#xff1a;直接使用线性刻度表示音量&#xff0c;例如在0.0&#xff08;最小音量&#xff09;到1.0&#xff08;最大音量&#xff09;的范围内。对…

『 Linux 』缓冲区(万字)

文章目录 &#x1f9a6; 什么是缓冲区&#x1f9a6; 格式化输入/输出&#x1f9a6; 刷新策略&#x1fab6; 块缓冲(fully buffered)&#x1fab6; 无缓冲(unbuffered)&#x1fab6; 行缓冲(line buffered) &#x1f9a6; 现象解释&#x1f9a6; exit()与_exit()&#x1f9a6; 进…

list 的实现

目录 list 结点类 结点类的构造函数 list的尾插尾删 list的头插头删 迭代器 运算符重载 --运算符重载 和! 运算符重载 * 和 -> 运算符重载 list 的insert list的erase list list实际上是一个带头双向循环链表,要实现list,则首先需要实现一个结点类,而一个结点需要…

【代码随想录——回溯算法——四周目】

1.重新安排行程 1.1 我的代码&#xff0c;超时通不过 var (used []boolpath []stringres []stringisFind bool )func findItinerary(tickets [][]string) []string {sortTickets(tickets)res make([]string, len(tickets)1)path make([]string, 0)used make([]bool,…

JSON Web Token

JWT 什么是JWT JWT&#xff08;JSON Web Token&#xff09;是一种用于在各方之间作为JSON对象安全地传输信息的开放标准&#xff08;RFC 7519&#xff09;。该信息经过数字签名&#xff0c;因此是可验证和可信的。JWT 可以使用HMAC算法或使用RSA的公钥/私钥对进行签名 JWT的…

win10键盘按乱了,如何恢复?

今天键盘被宝宝给按乱了&#xff0c;好不容易给重新调整回来&#xff0c;记录备忘&#xff1a; 1、win10的asdf和方向键互换了&#xff1a; 使用Fnw键来回切换&#xff0c;OK&#xff01; 2、键盘的win键失效&#xff0c;例如&#xff1a;按winD无法显示桌面。此时&#xf…

电动汽车电子系统架构

电动汽车的普及正在稳步发展&#xff0c;供应链的各个环节也在发生变化。它涵盖了制造电动汽车零件的原材料、化学品、电池和各种组件。与此同时&#xff0c;汽车充电基础设施也参与其中&#xff0c;它们正经历一个历史性的阶段&#xff0c;经过彻底的重新设计。它们的电气化以…

Wpf 使用 Prism 实战开发Day30

登录界面设计 一.准备登录界面图片素材&#xff08;透明背景图片&#xff09; 1.把准备好的图片放在Images 文件夹下面&#xff0c;格式分别是.png和.ico 2.选中 login.png图片鼠标右键&#xff0c;选择属性。生成的操作选择>资源 3.MyTodo 应用程序右键&#xff0c;属性&a…

如何修改开源项目中发现的bug?

如何修改开源项目中发现的bug&#xff1f; 目录 如何修改开源项目中发现的bug&#xff1f;第一步&#xff1a;找到开源项目并建立分支第二步&#xff1a;克隆分支到本地仓库第三步&#xff1a;在本地对项目进行修改第四步&#xff1a;依次使用命令行进行操作注意&#xff1a;Gi…

地质灾害位移应急监测站

地质灾害位移应急监测站是一种专门用于地质灾害预警和应急响应的设施&#xff0c;它能够实时监测和分析山体、建筑物、管道等的位移变化情况。以下是关于地质灾害位移应急监测站的详细介绍&#xff1a; 主要组成部分 传感器&#xff1a;安装于需要监测的位置&#xff0c;用于…

RK3588+FPGA+AI高性能边缘计算盒子,应用于视频分析、图像视觉等

搭载RK3588&#xff08;四核 A76四核 A55&#xff09;&#xff0c;CPU主频高达 2.4GHz &#xff0c;提供1MB L2 Cache 和 3MB L3 &#xff0c;Cache提供更强的 CPU运算能力&#xff0c;具备6T AI算力&#xff0c;可扩展至38T算力。 产品规格 系统主控CPURK3588&#xff0c;四核…