树(Tree)——(五)搜索二叉树的节点删除和销毁

2023-10-26

目录

节点删除的三种情况:

第一种情况:

第二种情况:

第三种情况

代码实现:

main函数


节点删除的三种情况:

节点删除总共分成三种情况:

第一种情况:

若为叶子节点则直接删除,如左图节点1,3 ,8或者右图的1,4,8。(若为单独一个根叶子要单独处理) 

若为单独一个根叶子

 

第二种情况:

若该节点,有一个节点,左或是右。因为只有一个节点,直接令祖父节点指向孙子节点,孙子节点的左右需要分开判断。如图中节点2(若该节点为根要单独处理) 

 

若该节点为根

 

 

第三种情况

若该节点含有两个子节点,一般的删除策略是用其右子树的最小结点代替待删除结点的数据,然后递归删除那个右子树最小结点。即将第三种情况转化为第二种情况。如下图所示,要删除结点2,则找到结点2的右子树的最小结点3并将其数据赋值给结点2,然后在删除结点3。

第三种情况的特殊情况分析(删除的节点为2,右节点5没有左节点。则把节点2换成节点5) 

 

 

代码实现:

main函数

//这里没有用栈和队列,前面写的函数这次用到的,以用递归为主,不然代码太过冗余

#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;

struct TreeNode
{
    TreeNode*_left;
    TreeNode*_right;
    int _data;
};

void midOrderITraverse(TreeNode * r) //递归,中序,左根右
{
    if(r)
    {
        midOrderITraverse(r->_left);
        printf("%d ",r->_data);
        midOrderITraverse(r->_right);
    }
}

//递归版插入
void insertBstRecusive(TreeNode** root ,int data)
{
    if((*root) == NULL)
    {
        (*root) =(TreeNode*)malloc(sizeof(TreeNode));
        (*root)->_data =data;
        (*root)->_left = (*root)->_right =NULL;
    }
    else if(data > (*root)->_data)
    {
        insertBstRecusive(&((*root)->_right),data);
    }
    else
    {
        insertBstRecusive(&((*root)->_left),data);
    }
}

//查找,递归版
TreeNode* searchBstRecursive(TreeNode* r,int find)
{
    if(r)
    {
        if(r->_data == find)
            return r;
        else if(r->_data > find)
            return searchBstRecursive(r->_left,find);
        else
            return searchBstRecursive(r->_right,find);
    }
}

//寻找最小值、最大值
TreeNode* getMinBst(TreeNode* r)
{
    if(r)
    {
        while(r->_left)
        {
            r=r->_left;
        }
        return r;
    }
    return NULL;
}
TreeNode* getMaxBst(TreeNode* r)
{
    if(r)
    {
        while(r->_right)
            r=r->_right;
        return r;
    }
    return NULL;
}

//查找父节点,迭代版
TreeNode* getParentBst(TreeNode*r,TreeNode * child)
{
    static TreeNode*parent = NULL;
    if(r)
    {
        if(r->_right == child || r->_left ==child)
            parent =  r;
        getParentBst(r->_left,child);
        getParentBst(r->_right,child);
    }
    return parent;
}

//删除节点
void deleteBst(TreeNode** r,TreeNode * pDel)
{
    TreeNode* t = *r;
    TreeNode * parent = getParentBst(t,pDel);
    TreeNode * minRight; //找到右节点为树的最小节点
    if(*r == NULL || pDel == NULL)
        return ;
    if(pDel->_left == NULL && pDel->_right == NULL) //第一种情况
    {
        if(*r == pDel)  //若删除的节点为根
        {
            free(t);
            *r = NULL;
            return;
        }
        if(parent->_left == pDel)
            parent->_left = NULL;
        else
            parent->_right = NULL;
        free(pDel);
        return;
    }
    else if(pDel->_left !=NULL && pDel->_right == NULL)//第二种
    {
        if(*r == pDel)
        {
            *r = pDel->_left; //这里 *r , t , pDel的_left 都可以
            free(pDel);
            return;
        }
        if(parent->_left == pDel)
            parent->_left = pDel->_left;
        else
            parent->_right = pDel->_left;
        free(pDel);
        return;
    }
    else if(pDel->_left == NULL && pDel->_right != NULL)//第二种
    {
        if(*r == pDel)
        {
            *r = pDel->_right;
            free(pDel);
            return;
        }
        if(parent->_left == pDel)
            parent->_left = pDel->_right;
        else
            parent->_right = pDel->_right;
        free(pDel);
        return;
    }
    else
    {
        //这里不讨论删除节点是否为根的情况
        //因为无论删除的是不是根节点,左右节点不为空,都需要替换来删除
        minRight = getMinBst(pDel->_right);
        pDel->_data = minRight->_data;
        parent = getParentBst(t,minRight);

        if(minRight == pDel->_right)
            parent->_right = minRight->_right;  //这里pDel的_right无论是否为空都可以
        else
            parent->_left = minRight->_right;
        free(minRight);
    }
}

//销毁树
void destroyBst(TreeNode* r)
{
    if(r)
    {
        destroyBst(r->_left);
        destroyBst(r->_right);
        free(r);
    }
}

int main()
{
     TreeNode *root=NULL;            //树的初始化
     insertBstRecusive(&root,30);     //利用例子建造树
     insertBstRecusive(&root,8);
     insertBstRecusive(&root,15);
     insertBstRecusive(&root,36);
     insertBstRecusive(&root,100);
     insertBstRecusive(&root,32);

     midOrderITraverse(root);
     putchar(10);
     TreeNode * ch = searchBstRecursive(root,36);
     if(ch == NULL)
         printf("no find");
     else
         cout<<ch->_data<<" ,find it"<<endl;

    deleteBst(&root,ch);
    midOrderITraverse(root);

    if(root == NULL)
        printf("Tree is empty");

    destroyBst(root);
    root = NULL; //main函数必须有,防止野指针
     return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

树(Tree)——(五)搜索二叉树的节点删除和销毁 的相关文章

  • solve Android studio click device manage no working

    Android Studio wants to know what kind of project you have to show the right menus click left in file tree on the root n
  • vuecli引入vue-amap地图组件(高德地图SDK)

    指南 组件 vue amap 1 前往高德开放平台注册开发者账号 在控制台申请Key 高德开放平台 高德开放平台 高德地图API 申请Key 获取Key 创建工程 开发指南 Web服务 API 高德地图API 2 安装vue amap np
  • 虚拟机配置

    1 Finalshell下载 Mac http www hostbuf com downloads finalshell install pkg Windows http www hostbuf com downloads finalshe
  • clang static analyzer源码分析(二)

    引子 在clang static analyzer源码分析 一 中我们简单介绍了 AnalysisConsumer 这个类以及基于AST树的语法层级的代码检查 今天简单介绍下 PathSensitiveChecks 的概念 以及如何对cla

随机推荐

  • STL:vectoer

    首先包含头文件 include
  • 重参数化技巧:高斯分布采样

    1 高斯分布采样 我们现在得到了有样本X得到的分布X N mu sigma 2 通过采样我们得到确定的隐变量向量 从而作为解码器的输入 采样这个操作本身是不可导的 但是我们可以通过重参数化技巧 将简单分布的采样结果变换到特定分布中
  • Fabric上搭建Hyperledger caliper进行性能测试

    Fabric介绍 推荐文章 Hyperledger 超级账本 是Linux基金会旗下的项目 Fabric是Hyperledger项目里最早也是目前应用最广泛的区块链项目 最初由IBM开发 后来捐助给基金会 是一个开源的企业级需要许可的分布式
  • Git Gui客户端软件连接及上传文件

    1 下载客户端软件 2 上传那个文件就在哪个文件下 git gui here 之后选择当前的目录创建仓库 3 关于操作在一下连接有 https blog csdn net qq 15509267 article details 836170
  • 关于mybatis使用pageHelper分页插件问题

    关于mybatis使用PageHelper分页插件冲突以及解决方案 分页插件其实 可以提高我们的开发效率 如果我们自己手写 1会嫌麻烦 2需要写两条一条写count一条写list 虽然他底层也是这么实现的 但是不需要我们手动来写 好的工具能
  • 大数据的入门级学习

    大数据方向的工作目前分为三个主要方向 01 大数据工程师 02 数据分析师 03 大数据科学家 04 其他 数据挖掘本质算是机器学习 不过和数据相关 也可以理解为大数据的一个方向吧 由于本人曾是大数据工程师的角色 我就这个方向做一些介绍 本
  • 从0开始使用vue-element-admin

    目录 安装node js及npm 安装nrm 安装vscode 汉化 推荐安装一些好用的扩展 安装vue element admin 框架登陆原理简单分析 本教程经亲测支持最新版4 0 1vue element admin 安装node j
  • RabbitMQ宕机后,消息100%不会丢失吗

    V xin ruyuanhadeng获得600 页原创精品文章汇总PDF 这篇文章 给不太熟悉MQ技术的同学 介绍一个生产环境中可能会遇到的问题 目前为止 你的RabbitMQ部署在线上服务器了 对吧 然后订单服务和仓储服务都可以基于Rab
  • 统计学习方法笔记(二)感知机

    感知机于1957年由Rosenblatt提出 是一种线性分类模型 属于判别模型 直接学习判别函数 是神经网络和支持向量机的基础 对于感知机的学习推导首先要知道他的模型是什么 然后是学习策略 损失函数 最后是学习算法 1 感知机的模型 假设空
  • vue设置全局时间格式化

    vue前台需要用户能看得懂的时间格式如常见的 2021 03 10 12 02 35 但是后台数据库则需要时间格式如LocalDateTime 2021 03 10T15 31 01 或者Date类型的 如果数据不经过处理 直接显示 肯定可
  • 如何在Windows上搭建web站点,并发布到公网?1-1

    系列文章 Windows用户如何安装使用cpolar内网穿透工具 如何在Windows上搭建web站点 并发布到公网 1 1 如何在Windows上搭建web站点 并发布到公网 2 2 如何在Windows下搭建WordPress博客站点
  • maven 引入qrcode.jar

    mvn install install file Dfile e QRCode jar DgroupId QRCode DartifactId QRCode Dversion 3 0 Dpackaging jar 3 在pom xml中增加
  • 逆变器STM32储能逆变器 BOOST 全桥 基于STM32F103设计,具有并网充电、放电

    逆变器STM32储能逆变器 BOOST 全桥 基于STM32F103设计 具有并网充电 放电 并网离网自动切换 485通讯 在线升级 风扇智能控制 提供过流 过压 短路 过温等全方位保护 基于arm的方案区别于dsp 有PCB 原理图及代码
  • 图像质量评估指标——SSIM介绍及计算方法

    图像质量评估指标 SSIM介绍及计算方法 SSIM全称为Structural Similarity 即结构相似性 用于评估两幅图像相似度的指标 常用于衡量图像失真前与失真后的相似性 也用于衡量模型生成图像的真实性 如图像去雨 图像去雾 图像
  • vue 集成ag-grid 组件,通过筛选条件操作列显示与隐藏

    关键代码 this columnApi setColumnVisible item false 此处item的位置 为ag grid列数据里面的colid 如无此项 可以用field的值来代替
  • 使用IBM SPSS Modeler进行随机森林算法预测

    IBM SPSS产品系列最主要的两款软件为IBM SPSS Statistics和IBM SPSS Modeler IBM SPSS Statistics主要用于统计分析 如均值比较 方差分析 相关分析 回归分析 聚类分析 因子分析 非参数
  • GDB交叉编译与问题解决

    GDB使用 交叉编译 Program received signal SIGILL Illegal instruction Program received signal SIGPIPE Broken pipe 交叉编译 bin bash
  • Linux项目实战——五子棋(单机人人对战版)

    Linux操作系统项目实战 五子棋 GIF 目录 Linux操作系统项目 五子棋 一 问题导引 二 实现要求 三 五子棋原理 1 落子数据信息保存载体 2 落子思路 3 判断 五子连珠 四 项目实现步骤 创建目录及文件 1 在Linux环境
  • 两个sed小技巧

    在写shell时使用sed处理一些输出 遇到两个问题 在网上找到了相应的解决办法 在此处备份一下 sed处理空字符 空字符 它的ASCII码值为0 在sed中如何标识空字符呢 看下面的例子 find print0 sed e s x0 n
  • 树(Tree)——(五)搜索二叉树的节点删除和销毁

    目录 节点删除的三种情况 第一种情况 第二种情况 第三种情况 代码实现 main函数 节点删除的三种情况 节点删除总共分成三种情况 第一种情况 若为叶子节点则直接删除 如左图节点1 3 8或者右图的1 4 8 若为单独一个根叶子要单独处理