备战蓝桥杯Day26 - 二叉搜索树查询和删除操作

news2025/1/11 17:14:08

一、查询

递归查询

寻找的值比根节点大,遍历右子树;

寻找的值比根节点小,遍历左子树。

    def qurey(self, node, val):
        if not node:  # 没有节点,返回空
            return None
        if node.data < val:
            return self.qurey(node.rchild, val)
        elif node.data > val:
            return self.qurey(node.lchild, val)
        else:
            return node

非递归查询 

通过比较,指针不断向下移动,直到找到节点。

 def query_no_rec(self, val):
        p = self.root
        while p:
            if p.data < val:
                p = p.rchild
            elif p.data > val:
                p = p.lchild
            else:
                return p
        return None

二、删除 

删除操作思路

删除操作比较难,需要考虑三种情况

1、删除叶子节点:直接删除

2、如果删除的节点只有一个孩子:将此节点的孩子与父亲链接,然后删除此节点。(如果删除的根节点只有一个孩子,删除根节点后,要重新更新一下根节点)

3、如果要删除的节点有两个孩子,将其右子树的最小节点(该节点最多有一个右孩子)替换当前节点,并删除。

详细解释

第一种情况:叶子节点

如果只有一个根节点,那么把根节点置为空就算删除。

如果是叶子节点,将该节点的父节点指向空,即为删除这个节点。ps:需要判断是左孩子还是右孩子

    def __remove_node_1(self, node):
        # 情况1:node是叶子节点
        if not node.parent:
            self.root = None
        if node == node.parent.lchild:
            node.parent.lchild = None
        else:
            node.parent.rchild = None

第二种情况:2.1 只有一个左孩子

2.1.1

如果是删除根节点,那么将根节点直接指向左孩子即可。

2.1.2

如果是树中的某一个左孩子,且只有一个左孩子,那么将该节点的父节点指向该节点的左孩子,并将指向该节点左孩子的指针指向该节点的父节点。

这个过程有点绕,多理解理解就好了,下面配图帮助理解。图中蓝线是指针变化后应该指向的位置。

2.1.3

如果是树中的某一个右孩子,且只有一个左孩子,那么将该节点的父节点指向该节点的左孩子,并将指向该节点左孩子的指针指向该节点的父节点。

实现代码

    def __remove_node_21(self, node):
        # 情况2.1:node只有一个左孩子
        if not node.parent:
            self.root = node.lchild
            node.parent.lchild = None
        elif node == node.parent.lchild:
            node.parent.lchild = node.lchild
            node.lchild.parent = node.parent
        else:
            node.parent.rchild = node.lchild
            node.lchild.parent = node.parent

第二种情况:2.2 只有一个右孩子 

2.2.1

如果是删除根节点,那么将根节点直接指向右孩子即可。

2.2.2

如果是树中的某一个左孩子,且只有一个右孩子,那么将该节点的父节点指向该节点的右孩子,并将指向该节点右孩子的指针指向该节点的父节点。

2.2.3

如果是树中的某一个右孩子,且只有一个右孩子,那么将该节点的父节点指向该节点的右孩子,并将指向该节点右孩子的指针指向该节点的父节点。

实现代码

    def __remove_node_22(self, node):
        # 情况2.2:node只有一个右孩子
        if not node.parent:
            self.root = node.rchild
        elif node == node.parent.lchild:
            node.parent.lchild = node.rchild
            node.rchild.parent = node.parent
        else:
            node.parent.rchild = node.rchild
            node.rchild.parent = node.parent

 第三种情况:左右两个孩子都有

3.1 在右子树中寻找最小的数。因为你删除的那个节点需要有数字替代,那么就是右子树中最小的那个数。

3.2 for循环遍历右子树的左孩子,找到最小的值。

3.3 把找到的最小的数替换到要删除的节点位置。

3.4 判断我们找到的最小数是只有右孩子的情况还是叶子节点的情况。这个节点不可能会有左孩子的情况,因为我们寻找最小数的已经找到最后一个左孩子了。

实现代码

                min_node = node.rchild
                while min_node.lchild:
                    min_node = min_node.lchild
                node.data = min_node.data
                # 删除min_node节点
                if min_node.rchild:
                    self.__remove_node_22(node)
                else:
                    self.__remove_node_1(node)

删除操作整个实现

没有右孩子就是只有一个左孩子

没有左孩子就是只有一个右孩子

    def delete(self, val):
        if self.root:   # 不是空树查询节点
            node = self.query_no_rec(val)
            if not node:
                return False
            if not node.lchild and not node.rchild:  # 1. 叶子节点
                self.__remove_node_1(node)
            elif not node.rchild:   # 2.1只有一个左孩子
                self.__remove_node_21(node)
            elif not node.lchild:   # 2.3 只有一个右孩子
                self.__remove_node_22(node)
            else:  # 3.两个孩子都有
                min_node = node.rchild
                while min_node.lchild:
                    min_node = min_node.lchild
                node.data = min_node.data
                # 删除min_node节点
                if min_node.rchild:
                    self.__remove_node_22(node)
                else:
                    self.__remove_node_1(node)

ok这就是查询和删除操作!代码一定要自己手敲!多动手!勤思考!一定会有进步的! 

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

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

相关文章

Spring MVC 如何返回响应

上期我们讲请求的时候&#xff0c;每个方法返回的数据就是响应&#xff0c;我们也可以返回一个静态页面&#xff0c;设置响应的状态码&#xff0c;Header信息等。 1. 返回静态页面 我们先在项目的static文件夹下创建一个HTML文件作为我们返回的页面&#xff1a; <!DOCTYPE…

OLAP与数据仓库和数据湖

OLAP与数据仓库和数据湖 本文阐述了OLAP、数据仓库和数据湖方面的基础知识以及相关论文。同时记录了我如何通过ChatGPT以及类似产品&#xff08;通义千问、文心一言&#xff09;来学习知识的。通过这个过程让我对于用AI科技提升学习和工作效率有了实践经验和切身感受。 预热 …

粤嵌6818嵌入式开发入门教程

学习目标 1.了解嵌入式开发 2.开发环境的搭建 3.Linux操作系统的基本操作 一、了解嵌入式开发 以应用为中心&#xff0c;以计算机技术为基础&#xff0c;软硬件可裁剪&#xff0c;适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。 1.嵌入式可以干…

再见 Pandas,又一数据处理神器

cuDF介绍 cuDF是一个基于Apache Arrow列内存格式的Python GPU DataFrame库&#xff0c;用于加载、连接、聚合、过滤和其他数据操作。cuDF还提供了类似于pandas的API。 GitHub&#xff1a; https://github.com/rapidsai/cudf Documentation&#xff1a; https://docs.rapids.a…

基于springboot+vue的大学生就业需求分析系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

2.亿级积分数据分库分表:增量数据同步之代码双写,为什么没用Canal?

1.亿级积分数据分库分表&#xff1a;总体方案设计 上一篇博客中写了一下积分数据分库分表的总体方案设计&#xff0c;里面说了采用应用程序代码双写的方式实现的增量数据同步&#xff0c;本篇就对这一块进行一些细化的介绍&#xff0c;包括&#xff1a; 为什么不用Canal监听数…

WebServer -- 八股(终章)

&#x1f442; Honey Honey - 孙燕姿 - 单曲 - 网易云音乐 目录 &#x1f33c;触类旁通 &#x1f6a9;线程 && 进程 线程与进程的区别 多线程锁是什么 进程 / 线程 / 协程 的区别 线程切换时&#xff0c;需要切换的状态 &#x1f382;并发 && 并行 并…

一起玩儿3D打印机——03 Marlin固件的获取和安装环境的配置

摘要&#xff1a;本文介绍Marlin固件的获取和安装环境的配置 Marlin是一款开源软件&#xff0c;其主页为&#xff1a;https://marlinfw.org/&#xff0c;首页正中就是下载连接&#xff0c;如下图所示&#xff1a; 单击下面的“Download Marlin 2.1.2.2”按钮就会进入下载页面&a…

Transformer学习笔记(一)

一、预训练 1、图像领域的预训练 通过 ImageNet 数据集我们训练出一个模型 A由于 CNN 的浅层学到的特征通用性特别强&#xff0c;我们可以对模型 A 做出一部分改进得到模型 B&#xff08;两种方法&#xff09;&#xff1a; 冻结&#xff1a;浅层参数使用模型 A 的参数&#x…

postgres中的hook机制

瀚高数据库 目录 环境 文档用途 详细信息 环境 系统平台&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;14,13,12,11 文档用途 1.了解使用postgres中的hook机制&#xff0c;在不更改内核代码的前提下完成一些定制化需求&#xff1b; 2.从底层理解插…

Visual Studio 2022 出现:E1696无法打开 源 文件 “stdafx.h“;E0020未定义标识符 “_TCHAR“错误解决办法

今天在用自己电脑上的visual studio2022写并行计算实验报告时出现了这种错误&#xff0c;但我在机房电脑vs2010版本运行时没有任何问题&#xff0c;于是我在网上找了解决办法&#xff0c;现总结如下。 1.报错E1696无法打开 源 文件 "stdafx.h"&#xff0c;解决办法&a…

移动通信网络AT指令

AT 命令是用来控制 TE(如 PC 等用户终端)和 MT(如移动台等移动终端)之间交互 的规则 AT 命令的返回值包括两部分,响应信息和结果码。 PLMN 移动通信网络PLMN = MCC + MNC,PLMN由MCC移动国家码和MNC移动网络码组成,例如:中国移动GSM的PLMN为:46000(MCC:460, M…

Internet Download Manager(IDM下载) v6.42.3 绿色版介绍

互联网下载管理器是一个广泛使用的软件&#xff0c;它可以帮助用户更好地管理和加速他们的下载。最新版本v6.42.3已经发布&#xff0c;它带来了一系列新功能和改进&#xff0c;让用户更加方便和快速地下载他们需要的文件。 新版本的互联网下载管理器增加了对最新浏览器的支持&…

通过键盘对机械臂进行操作

1 #include<myhead.h>2 #include<linux/input.h>3 #define SER_PORT 88884 #define SER_IP "192.168.116.225"5 #define CLI_PORT 99996 #define CLI_IP "192.168.65.129"7 int main(int argc, const char *argv[])8 {9 //1、创建用于连接…

题目:特殊的三角形(蓝桥OJ 3008)

问题描述&#xff1a; 解题思路&#xff1a; 可以先求出1~1e6每个位置是否有解&#xff0c;后计算前缀和再求出不同区间的和。&#xff08;时间复杂度小&#xff09; 进行dfs操作&#xff1a;依次组合1~1e6所有元素。并计算每一个组合的乘积&#xff0c;在该乘积位置的cnt加一。…

2024.3.15

1.单向循环链表 代码&#xff1a; #include"loop.h" //创建单向循环链表 loop_p create_loop_list() {loop_p H (loop_p)malloc(sizeof(loop));if(HNULL){printf("空间申请失败\n");return NULL;}H->len0;H->nextH;return H; } //创建节点 loop_p…

AJAX概念和axios使用、URL、请求方法和数据提交、HTTP协议、接口、form-serialize插件

AJAX概念和axios使用 AJAX概念 AJAX就是使用XMLHttpRequest对象与服务器通信&#xff0c;它可以使用JSON、XML、HTML和text文本等格式发送和接收数据&#xff0c;AJAX最吸引人的就是它的异步特性&#xff0c;也就是说它可以在不重新刷新页面的情况下与服务器通信&#xff0c;…

2024全国水科技大会-协办单位:海南立昇净水科技实业有限公司

海南立昇净水科技实业有限公司 集膜技术研发、生产和销售服务于一体的集团型高科技企业。30年来一直专注于“膜”技术研发&#xff0c;始终坚持走自主科技创新之路。在国内构建起由26家直属分公司和超过500家经销代理商组成的营销服务网络&#xff0c;立昇净水设备被广泛应用于…

前端学习之css伪元素选择器

伪元素选择器 &#xff08;注释是对各个内容的解释与理解&#xff09; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>伪元素选择器</title><!-- 双冒号开头一般都称为伪元素&#xff0c;…

STL容器之list类

文章目录 STL容器之list类1、list的介绍2、list的使用2.1、list的常见构造2.2、list的iterator的使用2.3、list空间增长问题2.4、list的增删查改2.5、list迭代器失效问题 3、list的模拟实现&#xff08;含反向迭代器&#xff09; STL容器之list类 1、list的介绍 list是序列容器…