Java删除二叉搜索树的任意元素的方法详解
作者:WFaceBoss 发布时间:2021-10-04 12:27:26
本文实例讲述了Java删除二叉搜索树的任意元素的方法。分享给大家供大家参考,具体如下:
一.删除思路分析
在删除二叉搜索树的任意元素时,会有三种情况:
1.1 删除只有左孩子的节点
节点删除之后,将左孩子所在的二叉树取代其位置;连在原来节点父亲元素右节点的位置,比如在图中需要删除58
这个节点。
删除58
这个节点后,如下图所示:
1.2 删除只有右孩子的节点:
节点删除之后,将右孩子所在的二叉树取代其位置;连在原来节点的位置,比如在下图中需要删除58
这个节点。
删除58这个节点后,如下图所示:
这里需要说明说一下,以上两种情况其实包含了叶子节点情况的,我们可以把叶子节点理解成只有左孩子的节点,也可以把它理解为只有右孩子的节点,只不过左孩子、右孩子为null
。
1.3 删除包含左右孩子的节点
如下图,二叉搜索树包含有左右孩子,假设现需要删除58
这个节点。
针对该种情况,分析如下:
我们把58
这个节点记为d
节点(包含有左子树与右子树),如下图所示:
针对这种节点删除情况需要把左子树与右子树融合起来,融合方法:
从d
这节点的左孩子与右孩子中找一个比d
节点还要大的节点取代d
节点,根据二叉搜索树的性质可知(左边节点<当前节点<右边节点),这个需要被找的节点存在于d
节点的右孩子节点中。
寻找规则:
寻找需要被删除节点58(d
)的后继的所有元素中,离 58 最近的且比 58 大的节点,在本例中为59
这个节点【即右子树中的最小值】,记为s
,如下图所示:
删除步骤:
(1)从d
的右子树中删除最小值,将删除最小值s
后的d
的右子树, 变为d
后继节点s
的右孩子,如下图所示:
(2)将d
节点(58
节点)的左子树,变为后继节点s
(59
节点)的左子树,如下图所示:
(3)将后继节点s
(59
节点)连接到d
节点(58
节点)父亲节点的右边,删除d
节点(58
节点)后,后继s
节点(59
节点)成为新的根,如下图所示:
二、编码实现二叉搜索树的任意元素
根据上述的分析,在此基础上进行编码,删除代码如下:
//从二叉搜索树中删除元素为e的节点
public void remove(E e) {
root = remove(root, e);
}
//删除以node为根的二叉搜索树中值为e的节点,递归算法
//返回删除节点后更新的二叉搜索树的根
private Node remove(Node node, E e) {
if (node == null)
return null;
if (e.compareTo(node.e) < 0) {//e<node.e (被删除元素e小于当前节点值e)
node.left = remove(node.left, e);
return node;
}
if (e.compareTo(node.e) > 0) {//e>node.e (被删除元素e大于当前节点值e)
node.right = remove(node.right, e);
return node;
} else {//e==node.e (被删除元素e等于当前节点值e)
//待删除节点左子树为空情况
if (node.left == null) {
Node rightNode = node.right;
node.right = null;
size--;
return rightNode;
}
//待删除节点右子树为空情况
if (node.right == null) {
Node leftNode = node.left;
node.left = null;
size--;
return leftNode;
}
//左右子树均不为空
//方法:找到比待删除节点大的最小节点,即待删除节点右子树的最小节点
//用这个节点顶替待删除节点的位置
Node successor = minimum(node.right);
successor.right = removeMin(node.right);
successor.left = node.left;
node.left = node.right = null;
return successor;
}
}
对于上述代码中的minimum函数,在5.3节中已经实现,此处同样也把代码列出来:
// 寻找二分搜索树的最小元素
public E minimum() {
if (size == 0) {
throw new IllegalArgumentException("BST is empty");
}
Node ninNode = minimum(root);
return ninNode.e;
}
// 返回以node为根的二分搜索树的最小值所在的节点
private Node minimum(Node node) {
if (node.left == null) {
return node;
}
//返回相应的节点的左子树的最小值
return minimum(node.left);
}
源码地址 https://github.com/FelixBin/dataStructure/blob/master/src/BST/BST.java
希望本文所述对大家java程序设计有所帮助。
来源:https://www.cnblogs.com/wfaceboss/p/10694736.html


猜你喜欢
- 需求说明在对图像进行处理时,经常会有这类需求:想通过阈值对图像进行二值化分割,以提取自己感兴趣的区域,常见的阈值分割方法有常数分割、最大类间
- 本文为大家分享了Android Studio下载和配置教程,供大家参考,具体内容如下1.下载Android Studio官网下载
- 人人客户端有一个特效还是挺吸引人的,在主界面手指向右滑动,就可以将菜单展示出来,而主界面会被隐藏大部分,但是仍有左侧的一小部分同菜单一起展示
- 在这里,记录我在项目中使用log4net记录本地日志的步骤。在不会之前感觉很难,很神秘,一旦会了之后其实没那么难。其实所有的事情都是一样的,
- 本文实例为大家分享了android自定义波浪加载动画的具体代码,供大家参考,具体内容如下效果图1.自定义控件 WaveViewpackage
- 1. 算法分析根据概率将奖品划分区间,每个区间代表一个奖品,然后抽取 随机数,反查落在那个区间上,即为所抽取的奖品。2. 代码核心
- 如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作。同时,这个问题在Stack Overflow
- 概要设计模式是一门艺术,如果真正了解这门艺术,你会发现,世界都将变得更加优美。定义定义一个用于创建对象的接口,让其子类去决定实例化那个类使用
- 一、问题来源项目中遇到 json 模型映射成 RadialGradient 组件的需求,其他参数正常传递即可;唯独 radius 参数效果有
- 实例如下://图片到byte数组 public byte[] image2byte(String path){ byte[] d
- 本文实例讲述了C#实现基于Base64的加密解密类。分享给大家供大家参考。具体如下:这个C#类是一个基于Base64的加密和解密类,用户可以
- 如果只想查看注解,请跳到文章末尾部分简介在前后端进行数据交互中,在前端把数据传送到后端前,一般会先进行校验一次,校验成功之后,才把数据发送到
- Android Studio软件下载地址如下:下载:http://www.android-studio.org/index.php/down
- 在C#语言中,DateTime是用来表示时间的类,在C#的DateTime时间类中,提供了好像时间对象加减法操作,可用于某一个时间对象加减
- 1. 概述:将一个具体类的实例化交给一个静态工厂方法来执行,它不属于GOF的23种设计模式,但现实中却经常会用到2. 模式中的角色2.1 工
- 一、案例场景遇到过这样的场景,在定义一个static修饰的Map时,使用了大量的put()方法赋值,就类似这样——public static
- TM的作用我们根据源码解读画出了下图,该图示展现了TM在整个Seata AT模式的分布式事务中所起的作用:从上图中可以看出,TM主要有两个作
- 应用开发的时候,有时我们需要将一些图片进行预览,例如:相片管理的应用。这个时候用ListView的话就显得不是太合适了,因为Li
- 本文实例为大家分享了Android studio实现简单计算器的具体代码,供大家参考,具体内容如下需求分析及概要设计目的开发一个简单的计算器
- 前言在上网的时候我们常常遇到文件上传的情况,例如上传头像、上传资料等;当然除了上传,遇见下载的情况也很多,接下来看看我们 servlet 中