(二叉树)二叉搜索树的查找、插入和删除

2023-11-18

1.二叉搜索树简介

二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉搜索树。二叉搜索树的特点之一即是其中序遍历为升序。

2.二叉搜索树的查找

根据二叉搜索树的性质,每个结点的值都是大于其左子结点值(左子结点非空)并且小于其右子结点值(右子结点非空),因此可以考虑二分查找的方法:比较目标值与当前结点值,如果目标值大于当前结点值,那么说明目标值不可能存在于当前结点的左子树中,应当再从其右子树中去查找;如果目标值小于当前结点值,那么说明目标值不可能存在于当前结点的右子树中,应当再从其左子树中去查找;如果目标值等于当前结点值,就返回当前结点,因此就不难写出代码了:

TreeNode* searchBST(TreeNode* root, int val) {
        if(!root)return NULL;   //如果到了空结点依然没找到,说明不存在
        
        if(root->val==val)return root;   //目标值等于当前结点值则返回当前结点
        if(root->val>val)    //目标值小于当前结点值,就从左子树中去查找
            return searchBST(root->left,val);
        
        return searchBST(root->right,val);   //目标值大于当前结点值,就从右子树中去查找

3.二叉搜索树的插入

要想将结点插入到二叉搜索树中,那么首先就需要找到插入的位置,那插入的位置怎么找呢?实际上,将结点插入到二叉搜索树中的方法并不唯一,举个例子:
向下面二叉搜索树中插入结点2:
在这里插入图片描述
插入的结果并不唯一:
在这里插入图片描述
在这里插入图片描述
当然不止这两种插入方式,这里介绍一种比较简单的方法,具体的方法如下:如二叉查找,比较待插入结点值(目标值)与当前结点值的大小,如果目标值大于当前结点值,那么说明应当将目标结点插入到右子树中;如果目标值小于当前结点值,那么说明应当将目标结点插入到左子树中,如果搜索到空结点,说明目标结点就应该插入这个空结点的位置了,这种方法实现结果就如上面第二种插入方式,代码如下:

TreeNode* insertIntoBST(TreeNode* root, int val) {
        
        if(!root)    //如果当前结点值为空,那么说明应当将目标结点插入到该空结点位置,就直接新建
        {
            TreeNode* newNode=new TreeNode(val);
            return newNode;
        }
        
        if(root->val==val)return root;   //如果目标结点值与当前结点值相同,就直接返回当前结点
        
        if(root->val<val)  //如果目标结点值大于当前结点值,就在右子树中进行查找
            root->right=insertIntoBST(root->right,val);
        
        else root->left=insertIntoBST(root->left,val);//如果目标结点值小于当前结点值,就在左子树中进行查找
        
        return root;   //返回结点
    }

4.二叉搜索树的删除

二叉搜索树的删除是比较麻烦的,删除结点还是需要先找到待删除结点的位置,找到待删除结点实际上就是二叉搜索树的查找了,这里就不多说了,主要说一下找到待删除结点后该怎么操作。这里一共有以下几种情况:
①待删除结点没有子结点;
②待删除结点左子树为空,右子树非空;
③待删除结点右子树为空,左子树非空;
④待删除结点左右子树皆非空。
第①种情况比较简单,直接返回空结点即可,现在来说下其他情况:
对于第②种情况,举个例子:删除下面二叉搜索树中的1
在这里插入图片描述
那么删除后的结果就应该将2结点移到1结点,如下:
在这里插入图片描述
由此也可总结出第②种情况的删除方法:从当前结点的右子结点开始,一直遍历左子结点,来在当前结点的右子树中找到最小值结点,然后将最小值赋值给当前结点值,再删除最小值结点。

需要注意的是,最小值结点可能是叶子结点,也可能还有右子树,如果是叶子节点,那么直接让该最小值结点的双亲结点的左子树指针指向NULL即可;

如果最小值结点还有右子树的话,如在上图中继续删除3结点,就还需要再处理3结点的右子树,那么就只需要将最小值结点的右子树接在最小值结点双亲结点的左子树上即可,换句话说,就是将图中的结点4接在结点3的双亲结点5的左子树上。

除此之外,还有一种特殊情况,即是当前结点的右子结点就是最小值结点了,那么说明其右子结点的左子树必定为空了,此时只需将其右子结点的值赋值给当前结点,并将其右子结点的右子树接到当前结点的右子树上即可。

实现代码如下:

                //在右子树中找到最小结点值来替换当前根结点值
                TreeNode* rightMin=root->right;
                TreeNode* lastMin=root;   //保存双亲结点
                while(rightMin->left)
                {
                    lastMin=rightMin;   //保存上一个结点
                    rightMin=rightMin->left;  //最小结点值必定是在根结点右子结点的左子树中找
                }
                
                root->val=rightMin->val;   //将找到的最小结点值赋值给根结点
                
                if(lastMin==root)lastMin->right=rightMin->right;  //如果根结点的右子结点就是右子树中最小的了,即右子结点
                                                          的左子结点为空,就直接将右子结点的右子树接到根结点右子树上即可
                else lastMin->left=rightMin->right;   //否则就将最小值结点的右子树接到最小结点的上一个结点的左子树上

第③种情况,左子树非空,右子树为空,删除的方法与上述类似,就不多说了;
第④种情况,对于左右子树均非空的情况,其实就既可以从左子树中找到最大结点来取代当前结点,也可以从右子树中找到最小结点来取代当前结点,两种方法都是可以的。

综合以上,代码如下:

TreeNode* deleteNode(TreeNode* root, int key) {
        
        if(!root)return NULL;
        
        if(root->val==key)   //根结点即是要删除的
        {
            if(!root->left&&!root->right)//左右皆空
                return NULL;
            
            else if(!root->left&&root->right)   //左子树空,右子树非空
            {
                //在右子树中找到最小结点值来替换当前根结点值
                TreeNode* rightMin=root->right;
                TreeNode* lastMin=root;
                while(rightMin->left)
                {
                    lastMin=rightMin;   //保存上一个结点
                    rightMin=rightMin->left;  //最小结点值必定是在根结点右子结点的左子树中找
                }
                
                root->val=rightMin->val;   //将找到的最小结点值赋值给根结点
                
                if(lastMin==root)lastMin->right=rightMin->right;  //如果根结点的右子结点就是右子树中最小的了,即右子结点的左子结点为空,就直接将右子结点的右子树接到根结点右子树上即可
                else lastMin->left=rightMin->right;   //否则就将最小值结点的右子树接到最小结点的上一个结点的左子树上
                
            }
            else    //左子树非空,右子树空  或者 左右子树均非空   均非空的情况下即可以在左子树中找最大的也可以在右子树中找最小的
            {
                //在左子树中找到最大结点值来替换当前根结点值
                TreeNode* leftMax=root->left;
                TreeNode* lastMax=root;
                while(leftMax->right)
                {
                    lastMax=leftMax;   //保存上一个结点
                    leftMax=leftMax->right;  //最大结点值必定是在根结点左子结点的右子树中找
                }
                
                root->val=leftMax->val;   //将找到的最小结点值赋值给根结点
                
                if(lastMax==root)lastMax->left=leftMax->left;   //如果根结点的左子结点就是左子树中最大的了,即左子结点的右子结点为空,就直接将左子结点的左子树接到根结点左子树上即可
                else lastMax->right=leftMax->left;  //否则就将最大值结点的左子树接到最大结点的上一个结点的右子树上
            }
        }
        else if(root->val>key)
            root->left=deleteNode(root->left,key);   //如果当前结点值大于目标值,就从左子树中删除目标值
        else root->right=deleteNode(root->right,key);   //如果当前结点值小于目标值,就从右子树中删除目标值
        
        
        return root;
        
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(二叉树)二叉搜索树的查找、插入和删除 的相关文章

  • 机器学习在交通标志检测与精细分类中的应用

    导读 数据对于地图来说十分重要 没有数据 就没有地图服务 用户在使用地图服务时 不太会想到数据就像冰山一样 用户可见只是最直接 最显性的产品功能部分 而支撑显性部分所需要的根基 往往更庞大 地图数据最先是从专业采集来的 采集工具就是车 自行
  • python学习笔记2

    if语法 if True print 条件成 执 的代码1 print 条件成 执 的代码2 下 的代码没有缩进到if语句块 所以和if条件 关 print 我是 论条件是否成 都要执 的代码 if else if 条件 条件成 执 的代码
  • linux查看用户登录时间以及命令历史

    1 查看当前登录用户信息 who命令 who缺省输出包括用户名 终端类型 登陆日期以及远程主机 who var log wtmp 可以查看自从wtmp文件创建以来的每一次登陆情况 1 b 查看系统最近一次启动时间 2 H 打印每列的标题 u
  • 转载-STM32片上FLASH内存映射、页面大小、寄存器映射

    原文地址 http blog chinaunix net uid 20617446 id 3847242 html 本文以STM32F103RBT6为例介绍了片上Flash Embedded Flash 若干问题 包括Flash大小 内存映
  • LAMP框架的架构与环境配置

    1 LAMP架构的相关知识 1 1 LAMP架构的概述 LAMP架构是目前成熟的企业网站应用模式之一 指的是协同工作的一整套系统和相关软件 能够提供动态Web站点服务及其应用开发环境 LAMP是一个缩写词 具体包括Linux操作系统 Apa
  • 神经网络训练中batch的作用(从更高角度理解)

    1 什么是batch batch 翻译成汉语为批 一批一批的批 在神经网络模型训练时 比如有1000个样本 把这些样本分为10批 就是10个batch 每个批 batch 的大小为100 就是batch size 100 每次模型训练 更新

随机推荐

  • CPU流水线与指令乱序执行

    青蛙见了蜈蚣 好奇地问 蜈蚣大哥 我很好奇 你那么多条腿 走路的时候先迈哪一条啊 蜈蚣听后说 青蛙老弟 我一直就这么走路 从没想过先迈哪一条腿 等我想一想再回答你 蜈蚣站立了几分钟 它一边思考一边向前 蹒跚了几步 终于趴下去了 它对青蛙说
  • Http通用短信接口开发经验及具体开发实现

    支持所有开发语言的调用 苹果IOS操作系统和WindowsPhone手机操作系统可参考执行 一 Webservice接口 1 webservice返回集合对照表 返回值 返回值说明 问题描述 2 帐号 密码不正确 1 序列号未注册2 密码加
  • 房价预测--利用Python进行数据分析

    原文链接 https www kaggle com pmarcelino comprehensive data exploration with python notebook 在这篇文章中 我对原文的结论翻译并加入自己的一些理解 如有不当
  • OCR算法综述与编程实现

    OCR算法综述与编程实现 OCR Optical Character Recognition 光学字符识别 是一种将图像中的文字转换为可编辑文本的技术 它在许多领域中发挥着重要作用 如文档扫描 自动化数据输入和图像搜索等 本文将对几种常见的
  • vue初识之自定义指令

    目录 一 简介 二 组成 三 分类 1 全局自定义指令 2 私有自定义指令 四 总结 一 简介 Vue中的自定义指令是一种扩展Vue功能的方式 可以用来封装常用的DOM操作或者添加一些特殊的行为 自定义指令可以在Vue实例中全局注册或者局部
  • Python 基础(一):入门必备知识

    目录 1 标识符 2 关键字 3 引号 4 编码 5 输入输出 6 缩进 7 多行 8 注释 9 数据类型 10 运算符 10 1 常用运算符 10 2 运算符优先级 基础 进阶 爬虫 自动化 数据分析 编写小游戏 趣味 Python 文档
  • Elasticsearch入门简单版

    文章目录 Elasticsearch 入门与深入 一 Elasticsearch介绍 1 主要功能 2 版本与升级 新特性 5 x 新特性 6 x 新特性 7 x 二 ELK 家族成员介绍 Logstash Kibana Elastic B
  • 电驴无限制 服务器,全球最大电驴服务器eDonkeyServer No2消失

    位于瑞典的电驴服务器eDonkeyServer No2是在比利时的Razorback 2 0服务器和德国DonkeyServer系列服务器之后全球最大的电驴服务器 然而目前已经不能访问 上个月底 10月底 包括eDonkeyServer N
  • SonarQube扫描代码规则设置

    Java自带的内嵌规则有400多条 太全了 导致扫描检测到的bug太多 可以根据公司项目需求自定义规则 创建质量配置 切换到质量配置右上角点击创建 取名并指定你要检测的开发语言 上级选择没有 可以在搜索配置分类选一下 可以快速定位 将我们新
  • Python 六大数据类型

    一 数字型 一 整型 1 整型 int 在数字中 正整数 0 负整数都称为整型 2 二进制整型 也可用二进制表示整型 print自动转换为十进制 二 浮点型 1 浮点型 float 含有小数点的数据都是浮点型 三 布尔型 布尔型 bool
  • SQL中去掉字符串中最后一个字符(小技巧)

    长度减一就可以了 select left 字段名 len 字段名 1 from 表名
  • 基于SpringBoot的爱心家园服装捐赠系统

    目录 1 项目介绍 2 项目技术 3 运行环境 4 项目介绍 5 项目代码 5 运行截图 6 源码获取 1 项目介绍 角色 管理员 用户 管理员 管理员登录系统后 可以对首页 个人中心 用户管理 捐赠记录管理 论坛管理 留言管理 心愿管理等
  • 软件全家桶-持续收录中(个人常用软件)

    下载网盘 下文附有官网地址 也可自行从官网下载 链接 https pan baidu com s 1YCOUyEozR6KLsNcG3W BtA 提取码 a4ni 01 截屏软件snipaste windows mac 版本 中文官网 ht
  • JavaScript基础详细思维导图(纯分享,不加水的那种)

    JavaScript比较基础重要知识的思维导图分享给大家 希望能给大家提供帮助 用到的工具是xmind 思维导图是小M 自己学习后总结出来的 比较适合新手 比较推荐UU们自己构造一个属于自己的思维导图 对知识的理解和记忆会更有帮助 这里还有
  • LINK : warning LNK4068: /MACHINE not specified; defaulting to IX86

    win32下汇编程序开发时 当连接时出现 LINK warning LNK4068 MACHINE not specified defaulting to IX86 这样的警告 解决方式 link subsystem windows mac
  • Linux下yum命令

    Yum 全称为 Yellow dog Updater Modified 是一个在Fedora中的Shell前端软件包管理器 基於RPM包管理 能够从指定的服务器自动下载RPM包并且安装 可以自动处理依赖性关系 并且一次安装所有依赖的软体包
  • 代码评审工具Phabricator安装和部署

    1 安装 1 1 安装要求 Phabricator是一个LAMP应用套件 因此最基本的要求就是LAMP环境 Linux Linux的不同发行版及变种是必需的 MacOS X是一个可接受的Linux变种 Windows不是 Phabricat
  • 第二篇 AlexNet——模型精讲

    文章目录 摘要 1 创新点 2 模型结构 3 模型特点 4 Pytorch官方实现 摘要 AlexNet是由Alex Krizhevsky 提出的首个应用于图像分类的深层卷积神经网络 该网络在2012年ILSVRC ImageNet Lar
  • 什么是模式识别

    什么是模式识别 当我们人眼看到一幅画时 我们能够很清晰的知道其中哪里是动物 哪里是山 水 人等等 但是人眼又是如何识别和分辨的呢 其实很简单 人类也是在先验知识和对以往多个此类事物的具体实例进行观察的基础上得到的对此类事物整体性质和特点的认
  • (二叉树)二叉搜索树的查找、插入和删除

    1 二叉搜索树简介 二叉搜索树或者是一棵空树 或者是具有下列性质的二叉树 若它的左子树不空 则左子树上所有结点的值均小于它的根结点的值 若它的右子树不空 则右子树上所有结点的值均大于它的根结点的值 它的左 右子树也分别为二叉搜索树 二叉搜索