news 2026/1/11 5:01:31

二叉树的构建与增删改查(2) 删除节点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二叉树的构建与增删改查(2) 删除节点

前置知识:二叉树的构建和增删改查-CSDN博客

1.二叉树的删除特点

1.1 基本概念

二叉树的删除操作是指在二叉树中移除某个特定节点,同时需要保持二叉树的基本性质不变。删除操作比插入操作更为复杂,因为需要考虑被删除节点的子树如何重新连接到树上。

1.2 删除操作的三种主要情况

1.2.1 删除叶子节点(无子节点)

  • 这是最简单的情况,直接移除该节点即可
  • 示例:在二叉树中删除节点5(假设5是叶子节点)
    5 / \ 3 7
    删除后:
    3 \ 7

1.2.2 删除只有一个子节点的节点

  • 将该节点的子节点提升到被删除节点的位置
  • 示例:删除节点3(它只有右子节点7)
    5 / \ 3 8 \ 7
    删除后:
    5 / \ 7 8

1.2.3 删除有两个子节点的节点

这是最复杂的情况,通常有以下两种处理方法:

方法一:使用前驱节点(左子树的最大值)
  1. 找到被删除节点左子树中的最大值节点
  2. 用这个最大值节点替换被删除节点
  3. 删除原最大值节点(递归处理)
方法二:使用后继节点(右子树的最小值)
  1. 找到被删除节点右子树中的最小值节点
  2. 用这个最小值节点替换被删除节点
  3. 删除原最小值节点(递归处理)

示例:删除节点5

5 / \ 3 8 / \ / \ 2 4 7 9

使用后继节点方法:

  1. 找到右子树最小值7
  2. 用7替换5
  3. 删除原7节点

结果:

7 / \ 3 8 / \ / \ 2 4 9

2.操作流程

图示操作可见1.2

2.1 除叶子节点

  1. 定位需要删除的目标节点targetNode
  2. 查找targetNode的父节点parentNode,并判断其是否存在
  3. 确定targetNode是parentNode的左子树还是右子树
  4. 根据节点位置执行删除操作:
    • 若为左子节点:将parentNode.lChild置为null
    • 若为右子节点:将parentNode.rChild置为null

2.2 删除只有一个子树的节点

  1. 定位需要删除的目标节点targetNode
  2. 查找targetNode的父节点parentNode(需判断是否存在)
  3. 确定targetNode在parentNode中的位置(左子树或右子树)
  4. 根据targetNode的子节点情况进行处理:

情况一:targetNode是parentNode的左子树

  • 若targetNode存在左子节点:parentNode.lChild = targetNode.lChild
  • 若targetNode存在右子节点:parentNode.lChild = targetNode.rChild

情况二:targetNode是parentNode的右子树

  • 若targetNode存在左子节点:parentNode.rChild = targetNode.lChild
  • 若targetNode存在右子节点:parentNode.rChild = targetNode.rChild

2.3 删除有两子树的节点

  1. 定位目标删除节点targetNode
  2. 查找targetNode的父节点parentNode(需判断是否存在)
  3. 在targetNode的右子树中寻找最小值节点
  4. 用右子树最小值节点的值替换targetNode的值
  5. 删除右子树中的最小值节点

3. 前置操作

3.1 创建方法用于寻找targetNode

public TreeNode findTarget(TreeNode root, Integer target) { if (root == null || target == null) return null; TreeNode cur = root; while (cur != null) { if (cur.data.equals(target)) { return cur; } else if (cur.data < target) { cur = cur.rChild; } else { cur = cur.lChild; } } return null; }

3.2 创建方法用于去找要删除的节点的父节点

public TreeNode findParent(TreeNode root,Integer target){ if(root==null){ return null; } if((root.lChild!=null) && (root.lChild.data.equals(target))|| (root.rChild!=null) && (root.rChild.data.equals(target))){ return root; }else { if(root.lChild!=null && target<root.data){ return findParent(root.lChild,target); }else if(root.rChild!=null && target>root.data){ return findParent(root.rChild,target); }else { return null; } } }

3.3 寻找右子树的最小节点

public int findRightTreeMin(TreeNode node){ while (node.lChild!=null){ node = node.lChild; } int min = node.data; delete(root,min); return min; }

4.删除节点

4.1 删除的节点只有一个节点

if(root.lChild==null && root.rChild==null){//删除的是叶子节点 root=null; return; }

4.2 叶子节点

if (targetNode.lChild == null && targetNode.rChild == null) { // 叶子节点 // 确定targetNdoe 是parentNode的左子节点还是右子节点 if (parentNode.lChild != null && parentNode.lChild.data.equals(target)) { parentNode.lChild = null; }else if (parentNode.rChild != null && parentNode.rChild.data.equals(target)) { parentNode.rChild = null; }

4.3 两个子节点

if (targetNode.lChild != null && targetNode.rChild != null) { // 两个子节点的节点 int min = findRightTreeMin(targetNode.rChild);//寻找右子树最小的节点 targetNode.data = min; }

4.4 只有一个子节点的节点

if(parentNode.lChild!=null && parentNode.lChild.data.equals(target)){ // targetNode是parentNode的左子节点 if(targetNode.lChild!=null){//删除的是有子节点的节点 parentNode.lChild = targetNode.lChild; }else if(targetNode.rChild!=null){//删除的是有子节点的节点 parentNode.lChild = targetNode.rChild; } }else if(parentNode.rChild!=null && parentNode.rChild.data.equals(target)){ // targetNode是parentNode的右子节点 if(targetNode.lChild!=null){//删除的是有子节点的节点 parentNode.rChild = targetNode.lChild; }else if(targetNode.rChild!=null){//删除的是有子节点的节点 parentNode.rChild = targetNode.rChild; } }

完整代码:

//删除节点 public void delete(TreeNode root,Integer target){ if (root==null){ return; } //2.万一要删除的节点只有一个节点 if(root.lChild==null && root.rChild==null){//删除的是叶子节点 root=null; return; } //1.找要删除的节点 TreeNode targetNode = findTarget(root,target); if(targetNode==null){ return; } //3.找到父节点 TreeNode parentNode = findParent(root,target); // 请你进行讲解 if (targetNode.lChild == null && targetNode.rChild == null) { // 叶子节点 // 确定targetNdoe 是parentNode的左子节点还是右子节点 if (parentNode.lChild != null && parentNode.lChild.data.equals(target)) { parentNode.lChild = null; }else if (parentNode.rChild != null && parentNode.rChild.data.equals(target)) { parentNode.rChild = null; } } else if (targetNode.lChild != null && targetNode.rChild != null) { // 两个子节点的节点 int min = findRightTreeMin(targetNode.rChild);//寻找右子树最小的节点 targetNode.data = min; } else { // 只有一个子节点的节点 // 确定targetNdoe 是parentNode的左子节点还是右子节点 if(parentNode.lChild!=null && parentNode.lChild.data.equals(target)){ // targetNode是parentNode的左子节点 if(targetNode.lChild!=null){//删除的是有子节点的节点 parentNode.lChild = targetNode.lChild; }else if(targetNode.rChild!=null){//删除的是有子节点的节点 parentNode.lChild = targetNode.rChild; } }else if(parentNode.rChild!=null && parentNode.rChild.data.equals(target)){ // targetNode是parentNode的右子节点 if(targetNode.lChild!=null){//删除的是有子节点的节点 parentNode.rChild = targetNode.lChild; }else if(targetNode.rChild!=null){//删除的是有子节点的节点 parentNode.rChild = targetNode.rChild; } } }

总结:

删除二叉树中的节点需要根据节点类型(叶子节点、单子节点、双子节点)采取不同策略,同时保持二叉树的特性(如二叉搜索树的顺序性)。

删除叶子节点

直接移除该节点,并将其父节点的对应子节点指针置空。无需调整树结构。

删除单子节点

将该节点的唯一子节点提升到被删除节点的位置,保持树的连通性。

删除双子节点

对于有两个子节点的节点,通常采用以下两种方法之一:

方法1:前驱替换法找到左子树的最大节点(前驱),用其值替换待删除节点,然后递归删除前驱节点。

方法2:后继替换法找到右子树的最小节点(后继),用其值替换待删除节点,然后递归删除后继节点。

完整删除流程(二叉搜索树示例)
  1. 定位待删除节点及其父节点
  2. 根据节点类型选择删除策略
  3. 维护树结构完整性
  4. 返回更新后的树根节点
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/10 16:55:44

TVBoxOSC调试宝典:从问题诊断到实战精通的完整指南

掌握TVBoxOSC调试技巧&#xff0c;就像拥有了解决电视盒子问题的有效工具。无论是设备连接异常、界面卡顿还是功能失效&#xff0c;通过本文的深度解析&#xff0c;你都能快速定位并解决问题。 【免费下载链接】TVBoxOSC TVBoxOSC - 一个基于第三方项目的代码库&#xff0c;用于…

作者头像 李华
网站建设 2026/1/10 3:33:42

群晖影视库元数据自动获取终极指南:告别手动整理时代

还在为群晖Video Station中杂乱无章的影视信息而烦恼吗&#xff1f;您的影视库是否总是缺少海报、剧情简介和演员信息&#xff1f;今天我们将为您介绍一款强大的第三方插件&#xff0c;让您的群晖NAS影视管理体验焕然一新。 【免费下载链接】syno-videoinfo-plugin A simple we…

作者头像 李华
网站建设 2025/12/25 1:44:43

Twitch掉落自动化神器:5分钟搞定游戏奖励获取

还在为错过Twitch掉落奖励而烦恼吗&#xff1f;Twitch Drops Miner 让你彻底告别手动操作的烦恼&#xff0c;实现真正的自动化奖励获取。这款开源工具专为游戏玩家设计&#xff0c;能够在后台自动运行&#xff0c;帮你轻松获得各种游戏内福利。 【免费下载链接】TwitchDropsMin…

作者头像 李华
网站建设 2026/1/3 10:52:07

基于51单片机智能无线对讲机设计信道可调双工语音传输DIY902

本设计由主机和从机两部分组成。主机和从机之间通过2.4G无线进行语音通信。主从机由STC15W408AS单片机电路麦克风声音采集电路LM386声音功放模块电路LED指示灯电路按键电路NRF24L01无线模块电路电源电路组成。1、麦克风采集声音信号&#xff0c;LM386功放电路驱动播放。2、通过…

作者头像 李华
网站建设 2026/1/10 6:11:17

基于STM32单片机智能快递柜外卖柜扫码取件语音播报蓝牙无线APP/WiFi无线APP/摄像头视频监控/云平台DIY设计S368

STM32-S368-存取柜取件码二维码语音播报存件手机号录入后台数据4舵机OLED屏按键(无线方式选择)产品功能描述&#xff1a;本系统由STM32F103C8T6单片机核心板、OLED屏、&#xff08;无线蓝牙/无线WIFI/无线视频监控/联网云平台模块-可选择&#xff09;、键盘部分、语音播报模块接…

作者头像 李华
网站建设 2025/12/18 15:49:58

X-AnyLabeling终极部署指南:跨平台AI辅助标注解决方案

X-AnyLabeling终极部署指南&#xff1a;跨平台AI辅助标注解决方案 【免费下载链接】X-AnyLabeling Effortless data labeling with AI support from Segment Anything and other awesome models. 项目地址: https://gitcode.com/gh_mirrors/xa/X-AnyLabeling X-AnyLabel…

作者头像 李华