数据结构奇妙旅程之二叉平衡树

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱
ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如需转载还请通知˶⍤⃝˶
个人主页:xiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
系列专栏:xiaoxie的JAVA系列专栏——CSDN博客●'ᴗ'σσணღ*
我的目标:"团团等我💪( ◡̀_◡́ ҂)" 

( ⸝⸝⸝›ᴥ‹⸝⸝⸝ )欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​+关注(互三必回)!

一.二叉平衡树

1.二叉平衡树的概念

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

它的左右子树也分别为二叉搜索树

从上述概念以及图中可以看出,二叉搜索树具有以下特性:

1. 二叉搜索树中最左侧的节点是树中最小的节点,最右侧节点一定是树中最大的节点

2. 采用中序遍历遍历二叉搜索树,可以得到一个有序的序列 

2.二叉搜索树的主要操作

1. 查询

2.插入

1.插入的为一颗空树

直接插入即可

2.. 如果树不是空树,按照查找逻辑确定插入位置,插入新结点

根据二叉搜索树的性质插入节点,"左小右大"

  1. 对于树中的任意节点 n,其左子树中的所有节点的值都小于 n 的值,其右子树中的所有节点的值都大于 n 的值。
  2. 在插入新节点时,需要按照二叉搜索树的性质找到合适的位置插入,保持树的有序性。
  3. 插入节点后,需要调整树的结构,保证树仍然是一个二叉搜索树。

3.删除

假设删除节点cur那么cur有以下几种情况

1.cur 的左孩子为空,右孩子不为空,

2.cur 的右孩子为空,左孩子不为空.

3.cur 的左右孩子均为空.

4.cur 的左右孩子均不为空.

接下来博主将会通过画图的形式来演示这四种情况该如何删除节点

1.cur 的左孩子为空,右孩子不为空

 2.cur 的右孩子为空,左孩子不为空.

3. cur 的左右孩子均为空.

4. cur 的左右孩子均不为空.

1.假设我们需要删除节点70,我们首先需要通过遍历二叉搜索树,找到70这个节点的对应位置.

2.我们发现70这个节点,左右孩子均不为空,这个时候就不可以通过简单的删除就可以了,我们需要用到替换法,即在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被 删除节点中,再来处理该结点的删除问题.

2.1这里解释一下为什么是在它的右子树中寻找中序下的第一个结点(关键码最小),当需要删除一个节点时,如果该节点有右子树,则可以在右子树中找到中序遍历下的第一个节点(即右子树中最小的节点)来替代当前节点。这是因为右子树中的所有节点都大于当前节点,而右子树中最小的节点又小于右子树中的所有其他节点,所以用右子树中的最小节点来替代当前节点可以保持二叉搜索树的性质不变。

3.找到"替罪羊"节点 t 后我们就需要把要删除的节点cur使他的值等于t .

4.最后删除节点t即可.

4.二叉搜索树基本操作的Java代码实现

public class BinarySearchTree {public static class TreeNode {public TreeNode left;public TreeNode right;public int val;public TreeNode(int val) {this.val = val;}}public TreeNode root;/*** 查询节点是否存在* @author xiaoxie* @date 2024/3/6 10:44* @param val* @return boolean*/public boolean search(int val) {if(root == null) {System.out.println();return false;}TreeNode cur = root;while (cur != null) {if(val < cur.val) {cur = cur.left;} else if (val > cur.val) {cur = cur.right;}else {System.out.println("找到了");return true;}}System.out.println("该节点"+val+"不存在");return false;}/*** 插入节点* @author xiaoxie* @date 2024/3/6 10:47* @param val*/public void insertTreeNode(int val) {TreeNode node = new TreeNode(val);if(root == null) {root = node;return;}TreeNode parent = null;TreeNode cur = root;while (cur != null) {if(node.val < cur.val) {parent = cur;cur = cur.left;} else if (node.val > cur.val) {parent = cur;cur = cur.right;}else {System.out.println("节点值 " + val + " 已经存在于树中,不进行插入操作");return;}}//cur = nullif(node.val < parent.val) {parent.left = node;}else {parent.right = node;}}/*** 删除节点* 可以使用替罪羊的方法来实现* @author xiaoxie* @date 2024/3/6 12:15* @param val* @return boolean*/public boolean remove(int val) {//首先先找到是哪一个节点if(root == null) {return false;}TreeNode parent = null;TreeNode cur = root;while (cur != null) {if(cur.val > val) {parent = cur;cur = cur.left;} else if (cur.val < val) {parent = cur;cur = cur.right;}else {break;}}//cur == null 说明要删除的节点不在二叉搜索树上if(cur == null) {return false;}// cur有多种情况//1.cur 没有左右孩子//2.cur 只有左孩子//3.cur 只有右孩子//4.cur 有左右孩子 -- 需要使用替罪羊的方法来删除if(cur.right != null && cur.left != null) {TreeNode t = cur.right;TreeNode tp = cur;while (t.left != null) {tp = t;t = t.left;}cur.val = t.val;//使要删除的节点的值等于替罪羊节点//删除替罪羊节点if(tp.left == t) {tp.left = t.right;}else {//出现tp.right = t 的情况,t节点一开始就是叶子节点tp.right = t.right;}}else {//cur 只有右孩子if(cur.left == null && cur.right != null){if(parent == null) {root = cur.right;}else {if(parent.val < cur.val) {parent.right = cur.right;}else {parent.left = cur.right;}}}//cur 只有左孩子else if (cur.left != null && cur.right == null) {if(parent == null) {root = cur.left;}else {if(parent.val < cur.val) {parent.right = cur.left;}else {parent.left = cur.left;}}}//cur 没有左右孩子else  {if(parent == null) {root = null;}else {if(parent.val < cur.val) {parent.right = null;}else {parent.left = null;}}}}return true;}

 5.性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。 对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度 的函数,即结点越深,则比较次数越多。 但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

1.最优情况下,二叉搜索树为完全二叉树

其平均比较次数为:log N;

2.最差情况下,二叉搜索树退化为单支树

 其平均比较次数为: 2 / N

问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插入关键码,都可以 是二叉搜索树的性能最佳?

那就需要用到AVL树了通过旋转来使二叉搜索树变成完全二叉树的形式,这里博主就不过多的赘述了,如果感兴趣,可以为博主点上一个关注,在下一篇文章中,博主将详细解读AVL树

感谢你的阅读!

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

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

相关文章

Dubbo-记录

1.概念 Apache Dubbo 是一款 RPC 服务开发框架&#xff0c;用于解决微服务架构下的服务治理与通信问题&#xff0c;官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力&#xff0c; 利用 Dubbo 提供的丰富服务治理…

Linux最小系统安装无法查看IP地址

1&#xff0c;出现原因 服务器重启完成之后&#xff0c;我们可以通过linux的指令 ip addr 来查询Linux系统的IP地址&#xff0c;具体信息如下: 从图中我们可以看到&#xff0c;并没有获取到linux系统的IP地址&#xff0c;这是为什么呢&#xff1f;这是由于启动服务器时未加载网…

Decontam去污染:一个尝试

为了程序运行的便利性&#xff0c;不想将Decontam放到windows的Rstudio里面运行&#xff0c;需要直接在Ubuntu中运行&#xff0c;并且为了在Decontam时进行其他操作&#xff0c;使用python去运行R 首先你需要有一个conda环境&#xff0c;安装了R&#xff0c;Decontam&#xff0…

【b站咸虾米】1 Vue介绍 2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例

课程地址&#xff1a;【2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例】 https://www.bilibili.com/video/BV1pz4y1S7bC/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 感觉尚硅谷的Vue看完忘得差不多了&#xff0c;且之前学过咸虾米的unia…

使用css结合js实现html文件中的双行混排

此前写过一个使用flex布局实现html文件中的双行混排&#xff0c;但是感觉效果不佳。经过几天思考&#xff0c;我认为双行混排的要点其实是两个&#xff1a; 1、正文和批注的文字大小不同&#xff1b; 2、正文和批注的行距相互配合进行设定。 正文和批注的文字大小及行距都可…

【Python】进阶学习:OpenCV--一文详解cv2.namedWindow()

【Python】进阶学习&#xff1a;OpenCV–一文详解cv2.namedWindow() &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望…

【JavaEE初阶 -- 多线程】

认识线程&#xff08;Thread&#xff09;Thread类及常见方法 1.认识线程&#xff08;Thread&#xff09;1.1 线程1.2 进程和线程的关系和区别1.3 Java的线程和操作系统线程的关系1.4 创建线程 2. Thread类及常用的方法2.1 Thread的常见构造方法2.2 Thread的几个常见属性2.3 启动…

enumerate函数的用法

enumerate() 函数是 Python 内置函数之一&#xff0c;用于同时返回可迭代对象的索引和对应的值。 它的语法结构如下&#xff1a; enumerate(iterable, start0) iterable: 表示一个可迭代的对象&#xff0c;如列表、元组、字符串等。start: 可选参数&#xff0c;表示索引起始…

用c++实现约瑟夫和问题、埃拉托色尼筛法

3.2.1 约瑟夫环问题 【问题】 约瑟夫环问题(Josephds circle problem)由古罗马史学家约瑟夫提出&#xff0c;他参加并记录了公元66—70年犹太人反抗罗马的起义。约瑟夫作为一个将军&#xff0c;守住了裘达伯特城达47 天之久。在城市沦陷后&#xff0c;他和40名视死如归的将士在…

第十五届蓝桥杯模拟考试III_物联网设计与开发

编程题 一、基本要求 使用大赛组委会提供的四梯/国信长天物联网省赛套装&#xff08;基于STM32L071KBU微控制器设计&#xff09;&#xff0c;完成本试题的程序设计与调试。程序编写、调试完成后&#xff0c;选手需提交两个LoRa终端对应的hex文件&#xff0c;LoRa终端A对应的文…

SRS(Simple Realtime Server)

SRS(Simple Realtime Server - github) SRS 中文官网 docker安装srs ##&#xff08;安全组放开1935端口、8080端口&#xff09; docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 -p 8000:8000/udp -p 10080:10080/udp ossrs/srs:5推流 ## 不需要加端口 ffmpeg…

使用 Docker 部署 Next Terminal 轻量级堡垒机

1&#xff09;Next Terminal 介绍 官网&#xff1a;https://next-terminal.typesafe.cn/ GitHub&#xff1a;https://github.com/dushixiang/next-terminal 想必经常玩服务器的都了解过 堡垒机&#xff0c;类似于跳板机&#xff0c;但与跳板机的侧重点不同。堡垒机的主要功能是…