数据结构——有序二叉树的删除

news2025/1/8 0:20:48

在上一篇博客中,我们介绍了有序二叉树的构建、遍历、查找。

数据结构——有序二叉树的构建&遍历&查找-CSDN博客文章浏览阅读707次,点赞18次,收藏6次。因为数据的类型决定数据在内存中的存储形式。left right示意为左右节点其类型也为TreeNode,用于接受后续一系列操作,保持了结构的一致性。为什么left和right的类型为TreeNode?我们采用递归的方式实现。我们创建一个test类。https://blog.csdn.net/2301_78566776/article/details/144160961?spm=1001.2014.3001.5501这篇博客我们来介绍一下有序二叉树的删除。

删除操作

删除操作的步骤相对复杂,因为需要处理三种情况:

1.要删除的节点是叶子节点(没有子节点)

删除叶子节点
        1.找到要删除的节点targetNode
        2.找到targetNode的父节点(考虑父节点是否存在)
        3.确定targetNode是parentNode的左子树还是右子树
        4.根据前面的情况进行删除
        左子树:parentNode.left=null;右子树:parentNode.right=null;

2.要删除的节点只有一个子节点

删除有一个子树的节点
        1.找到要删除的节点targetNode
        2.找到targetNode的父节点(考虑父节点是否存在)
        3.确定targetNode是左子树还是右子树
        4.确定targetNode有的是左子树还是右子树
        5.targetNode有的是左子树
                 parentNode.left = targetNode.left;——删除的节点是父节点的左子树
                 parentNode.right = targetNode.left;——删除的节点是父节点的右子树
        6.targetNode有的是右子树:

                 parentNode.left = targetNode.right;——删除的节点是父节点的左子树
                 parentNode.right = targetNode.right;——删除的节点是父节点的右子树       

3.要删除的节点有两个子节点

对于第三种情况,通常的做法是找到要删除节点的中序后继(或中序前驱),将其值替换到要删除的节点上,然后删除这个中序后继(或中序前驱)。

删除有两个子树的节点
        1.找到要删除的节点targetNode
        2.找到targetNode的父节点(考虑父节点是否存在)
        3.去找targetNode的右子树的左子树当中的最小值
        4.将targetNode的值和最小值的值进行互换
        5.删除最小值——即删除叶子节点(替换删除)

Java代码如下:
public TreeNode Search(TreeNode node,int value) {
		if (node == null) {
            return null; 
        }
		if (value==node.data) {
            return node; 
        }else if(value<node.data){
        	if(node.left!=null) {
        		return Search(node.left,value);
			}
        }else {
        	if(node.right!=null) {
        		return Search(node.right,value);
			}
        }
        
		return null;
		// TODO Auto-generated method stub

	}
public TreeNode SearchParent(TreeNode node,int value){
	if (node == null) {
        return null; 
    }
	if((node.left!=null&&node.left.data==value)||(node.right!=null&&node.right.data==value)){
		return node;
	}else {
		if(node.left!=null&&value<node.data) {
			return SearchParent(node.left,value);
		}else if(node.right!=null&&value>node.data) {
			return SearchParent(node.right,value);
		}else {
			return null;
		}
	}
	
}

	public int delRightTreeMin(TreeNode node){
	    TreeNode tempNode = node;
	    while (tempNode.left !=null){
	        tempNode = tempNode.left;
	    }
	
	    return tempNode.data; //最值进行返回
	}


	public void delete(TreeNode node,int value){
		if (node == null) {//空树,直接返回
	        return; 
	    }
		
		if(node.left==null&&node.right==null) {//单节点树,直接置空
			node=null;
			return;
		}
		
		//先查询要删除的节点
		TreeNode targetNode=Search(node,value);
		
		if(targetNode==null) {//没有找到
			return;
		}
		
		//找父节点
		TreeNode parentNode=SearchParent(node,value);
		
		if(targetNode.left==null&&targetNode.right==null) {//如果targetNode是叶子节点
			if(parentNode.left!=null&&parentNode.left.data==targetNode.data){//如果target是parent的左子树
				parentNode.left=null;
			}else if(parentNode.right!=null&&parentNode.right.data==targetNode.data) {//如果target是parent的右子树
				parentNode.right=null;
			}
		}
		else if(targetNode.left!= null && targetNode.right!=null) {//如果targetNode有两个子节点
			int minValue = delRightTreeMin(targetNode.right); //找右子树的最小值
			delete(targetNode.right,minValue);
			targetNode.data = minValue;//互换最小值
		}
		else { //只有一个子节点的节点
			 if(targetNode.left !=null){ //当前要删除的节点有左子树
					  if(parentNode.left.data == targetNode.data){ //删除的节点是父节点的左子树
						  parentNode.left = targetNode.left;
					  }else {//删除的节点是父节点的右子树
						  parentNode.right = targetNode.left;
					  }
			 }
			 else {//当前要删除的节点有右子树
				 if(parentNode.left.data == targetNode.data){  //删除的节点是父节点的左子树
					 parentNode.left = targetNode.right;
	             }else {//删除的节点是父节点的右子树
	                 parentNode.right = targetNode.right;
	             }
			 }
		}				
	}

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

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

相关文章

深入理解 SQL 注入:原理、攻击流程与防御措施

深入理解 SQL 注入&#xff1a;原理、攻击流程与防御措施 在当今数字化的时代&#xff0c;数据安全已成为每个企业和开发者必须面对的重要课题。SQL 注入&#xff08;SQL Injection&#xff09;作为一种常见的网络攻击方式&#xff0c;给无数企业带来了巨大的损失。本文将深入…

android WebRtc 无法推流以及拉流有视频无声音问题

最近在开发使用WebRtc进行视频通话和语音通话&#xff0c;我使用的设备是MTK的手机&#xff0c;期间后台的技术人员几乎没法提供任何帮助&#xff0c;只有接口和测试的web端&#xff0c;有遇到不能推流。推流成功网页端有画面有声音&#xff0c;但是安卓端有画面&#xff0c;没…

微信小程序之手机归属地查询

微信小程序之手机归属地查询 需求描述 API申请和小程序设置 API申请 第一步&#xff1a;完整账号注册 我们需要来到如下网站&#xff0c;注册账号&#xff1a;万维易源 第二步&#xff1a;账号注册完成以后&#xff0c;点击右上角的控制台信息。 第三步&#xff1a;在控制…

【机器学习】机器学习的基本分类-监督学习-Lasso 回归(Least Absolute Shrinkage and Selection Operator)

Lasso 回归是一种线性回归方法&#xff0c;通过引入 ​ 正则化&#xff08;绝对值惩罚项&#xff09;约束回归系数&#xff0c;既能解决多重共线性问题&#xff0c;又具有特征选择能力。 1. Lasso 回归的目标函数 Lasso 的目标是最小化以下损失函数&#xff1a; 其中&#xff…

优化LabVIEW数据运算效率的方法

在LabVIEW中进行大量数据运算时&#xff0c;提升计算效率并减少时间占用是开发过程中常遇到的挑战。为此&#xff0c;可以从多个角度着手优化&#xff0c;包括合理选择数据结构与算法、并行处理、多线程技术、硬件加速、内存管理和界面优化等。通过采用这些策略&#xff0c;可以…

python学opencv|读取图像(四)imshow()函数尝试

【1】引言 前述已经学习了opencv读取图像的基本操作&#xff0c;包括下述链接&#xff1a; python学opencv|读取图像-CSDN博客 python学opencv|读取图像&#xff08;二&#xff09;保存彩色图像-CSDN博客 python学opencv|读取图像&#xff08;三&#xff09;放大和缩小图像…

MongoDB分片集群搭建及扩容

分片集群搭建及扩容 整体架构 环境准备 3台Linux虚拟机&#xff0c;准备MongoDB环境&#xff0c;配置环境变量。一定要版本一致&#xff08;重点&#xff09;&#xff0c;当前使用 version4.4.9 配置域名解析 在3台虚拟机上执行以下命令&#xff0c;注意替换实际 IP 地址 e…

MATLAB 最小二乘平面拟合(90)

MATLAB 最小二乘平面拟合(90) 一、算法介绍二、算法实现1.代码2.结果:一、算法介绍 平面方程: ax+by+cz+d = 0 执行任务:读取一组点云(这里用自定义生成的平面模拟点云代替,在其中添加了噪声来模拟真实的数据),使用最小二乘拟合平面,来输出平面参数,并可视化显示拟…

AI+电影特效产品化:开启电影人物年轻化新时代

随着人工智能技术的不断进步,它正在改变着我们生活的方方面面,包括娱乐产业。在电影制作领域,AI技术的应用尤其引人注目,尤其是在实现演员年轻化或老化效果方面。本文将介绍一款名为MyTimeMach

Appium 安装问题汇总

好生气好生气&#xff0c;装了几天了&#xff0c; opencv4nodejs 和 mjpeg-consumer 就是装不了&#xff0c;气死我了不管了&#xff0c;等后面会装的时候再来完善&#xff0c;气死了气死了。 目录 前言 1、apkanalyzer.bat 2、opencv4nodejs 3、ffmpeg 4、mjpeg-consume…

Cannot resolve symbol ‘ActivityThread‘ | Android 语法

背景 ActivityThread 是 Android 系统内部使用的一个类,它位于 android.app 包中,但在 Android SDK 的公共 API 中并没有公开。 由于 ActivityThread 是隐藏的内部类,因此在编写单元测试或功能开发时,无法直接引用它。可以使用反射来访问内部 API,或者使用依赖注入的方式…

探索自然语言处理奥秘(NLP)

摘要 自然语言处理&#xff08;NLP&#xff09;是人工智能领域的一个重要分支&#xff0c;它致力于使计算机能够理解、解释和生成人类语言。这项技术让机器能够阅读文本、听懂语音&#xff0c;并与人类进行基本的对话交流。 通俗理解 自然语言处理&#xff08;NLP&#xff09…

JAVAWeb中的Servlet学习

一 Servlet简介 1.1动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源.例如:html css js img ,音频文件和视频文件 动态资源 需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成,例如Servle…

「Mac畅玩鸿蒙与硬件40」UI互动应用篇17 - 照片墙布局

本篇将带你实现一个简单的照片墙布局应用&#xff0c;通过展示多张图片组成照片墙效果&#xff0c;用户可以点击图片查看其状态变化。 关键词 UI互动应用照片墙布局Grid 布局动态图片加载用户交互 一、功能说明 照片墙布局应用的特点&#xff1a; 动态加载多张图片组成网格布…

dhcpd服务器的配置与管理(超详细!!!)

前提条件&#xff1a; &#xff08;1&#xff09;虚拟机能够联网&#xff08;如果nat模式不能联网的看另一期&#xff09; CentOS7 NAT模式不能联网-CSDN博客 &#xff08;2&#xff09;系统是Centos8&#xff0c;因为下载的dhcp-server软件包版本和Centos7不匹配,如果你能成…

java基础概念47-ArrayList、LinkList和迭代器

一、ArrayList集合 1-1、ArrayList的两种添加信息的方式 1-2、ArrayList集合底层逻辑 1、利用空参创建的集合&#xff0c;在底层创建一个默认长度为0的数组 2、添加第一个元素时&#xff0c;底层会创建一个新的长度为10的数组 3、存满时&#xff0c;会扩容1.5倍。 4、如果…

oracle之用户的相关操作

&#xff08;1&#xff09;创建用户(sys用户下操作) 简单创建用户如下&#xff1a; CREATE USER username IDENTIFIED BY password; 如果需要自定义更多的信息&#xff0c;如用户使用的表空间等&#xff0c;可以使用如下&#xff1a; CREATE USER mall IDENTIFIED BY 12345…

ffmpeg转码与加水印

文章目录 转码 与加水印引入jar包代码ffmpeg安装错误解决方法 转码 与加水印 引入jar包 <dependency><groupId>net.bramp.ffmpeg</groupId><artifactId>ffmpeg</artifactId><version>0.6.2</version></dependency>代码 impo…

tomcat 运行加载机制解析

tomcat 运行加载机制 从tomcat jar包的加载顺序&#xff1a; tomcat的具体运行加载 可以从 start、setclasspath、catalina文件中看出来&#xff1a; start.bat执行 去找bin目录下的catalina.bat,catalina 或去找 bin\setenv.bat以获取标准环境变量&#xff0c;然后去找bin\…

策略模式实战 - 鸭展

该示例出自著名的《HeadFirst》系列的《HeadFirst设计模式》图书的第一个设计模式。用一个鸭子展览的小应用&#xff0c;一步步揭示了如何引入和使用策略模式将示例改造的完美一些。 文章目录 红头鸭与绿头鸭橡皮鸭和诱饵鸭用接口代替继承组合关系与策略模式 红头鸭与绿头鸭 当…