二叉排序树(BST)

news/2024/5/5 21:32:41/文章来源:https://blog.csdn.net/2301_77659011/article/details/133977964

二叉排序树

基本介绍

二叉排序树创建和遍历

class Node:"""创建 Node 节点"""value: int = 0left = Noneright = Nonedef __init__(self, value: int):self.value = valuedef add(self, node):"""添加节点node 表示要添加的节点"""if node is None:return# 判断要添加节点和当前子树根节点的大小if node.value < self.value:# 要添加节点小于当前子树根节点if self.left is None:# 如果当前子树左子节点为空,则直接将要添加的节点挂在左子节点上self.left = nodeelse:# 否则,递归当前子树的左节点,找到要放置的位置self.left.add(node)else:  # 要添加节点大于等于当前子树根节点if self.right is None:# 如果当前子树右子节点为空,则直接将要添加的节点挂在右子节点上self.right = nodeelse:# 否则,递归当前子树的右节点,找到要放置的位置self.right.add(node)def infix_order(self):"""中序遍历二叉树"""if self.left:self.left.infix_order()print(self.value)if self.right:self.right.infix_order()class BinarySortTree:"""二叉排序树"""root: Node = Nonedef add(self, node: Node):"""添加节点node: 要添加的节点"""if self.root is None:# 如果根节点为空,直接将新节点当做根节点self.root = nodeelse:# 否则,将新节点放在根节点下self.root.add(node)def infix_order(self):"""中序遍历"""if self.root:self.root.infix_order()else:print("二叉排序树为空...")arr = [7, 3, 10, 12, 5, 1, 9]
binary_sort_tree = BinarySortTree()
for i in arr:node = Node(i)binary_sort_tree.add(node)
binary_sort_tree.infix_order()

二叉排序树的节点删除

思路分析

代码实现

"""二叉排序树"""
class Node:"""创建 Node 节点"""value: int = 0left = Noneright = Nonedef __init__(self, value: int):self.value = valuedef add(self, node):"""添加节点node 表示要添加的节点"""if node is None:return# 判断要添加节点和当前子树根节点的大小if node.value < self.value:# 要添加节点小于当前子树根节点if self.left is None:# 如果当前子树左子节点为空,则直接将要添加的节点挂在左子节点上self.left = nodeelse:# 否则,递归当前子树的左节点,找到要放置的位置self.left.add(node)else:  # 要添加节点大于等于当前子树根节点if self.right is None:# 如果当前子树右子节点为空,则直接将要添加的节点挂在右子节点上self.right = nodeelse:# 否则,递归当前子树的右节点,找到要放置的位置self.right.add(node)def infix_order(self):"""中序遍历二叉树"""if self.left:self.left.infix_order()print(self.value)if self.right:self.right.infix_order()def search_delete(self, value: int):"""查找要删除的节点:param value: 要删除节点的值:return:"""if self.value == value:  # 当前节点就是要找的删除的节点,返回return selfelif value < self.value:  # 要删除的值小于当前节点的值,则在当前节点的左子树递归查找if self.left:return self.left.search_delete(value)return Noneelse:  # 要删除的值大于当前节点的值,则在当前节点的右子树递归查找if self.right:return self.right.search_delete(value)return Nonedef find_parent(self, value: int):"""查找要删除节点的父节点:param value: 要删除的节点值:return:"""if (self.left and self.left.value == value orself.right and self.right.value == value):return selfelse:# 如果要删除的值小于当前节点的值,且当前节点有左节点,则向左节点递归查找if value < self.value and self.left:return self.left.find_parent(value)# 如果要删除的值大于等于当前节点的值,且当前节点有右节点,则向右 节点递归查找elif value >= self.value and self.right:return self.right.find_parent(value)return None  # 没有找到父节点,返回空,表示没有父节点,即要删除的是根节点class BinarySortTree:"""二叉排序树"""root: Node = Nonedef add(self, node: Node):"""添加节点node: 要添加的节点"""if self.root is None:# 如果根节点为空,直接将新节点当做根节点self.root = nodeelse:# 否则,将新节点放在根节点下self.root.add(node)def infix_order(self):"""中序遍历"""if self.root:self.root.infix_order()else:print("二叉排序树为空...")def search_delete(self, value) -> Node:"""查找要删除的节点:param value: 要删除节点的值:return:"""if self.root:return self.root.search_delete(value)return Nonedef find_parent(self, value) -> Node:"""查找要删除节点的父节点:param value: 要删除节点的值:return:"""if self.root:return self.root.find_parent(value)return Nonedef find_and_delete_right_tree_min(self, node: Node) -> int:"""查找以 node 为根节点的二叉排序树的最小节点返回小节点的值并从该二叉排序树中删除最小节点:param node::return:"""t = nodewhile t.left:  # 因为要找最小节点,所以从二叉排序树的左子树中找t = t.left# 退出循环时,t 指向的就是最小节点val = t.valueself.delete_node(val)return valdef delete_node(self, value: int):"""删除接地那:param value: 要删除节点的值:return:"""if self.root is None:print("二叉树为空,不能删除节点...")return# 查找要删除的节点target_node = self.search_delete(value)if target_node is None:  # 找不到要删除的节点print(f"节点{value}不存在")returnif self.root.left is None and self.root.right is None:# 此时找到了要删除的节点,且二叉树只有一个节点,所以要删除的就是这唯一的一个节点self.root = Nonereturn# 查找要删除节点的父节点parent = self.find_parent(value)if target_node.left is None and target_node.right is None:# 此时说明要删除的节点是叶子节点# 进一步判断要删除的节点是父节点的左节点还是右节点if parent.left and parent.left.value == value:# 说明要删除节点是父节点的左子节点parent.left = Nonereturnif parent.right and parent.right.value == value:# 说明要删除节点是父节点的右子节点parent.right = Nonereturnelif target_node.left and target_node.right:# 要删除的节点有左右两棵子树# 从要删除节点的右子树中找到最小节点,获得该最小节点的值并删除该最小节点# 然后将最小节点的值赋值给要删除节点min_val = self.find_and_delete_right_tree_min(target_node.right)target_node.value = min_val# 同理,也可以从要删除节点的左子树找到最大节点,获得该最大节点的值并删除该最大节点# 然后将最大节点的值赋值给要删除节点else:# 要删除的节点只有一棵子树# 进一步确定要删除节点的子树是左子树还是右子树if target_node.left:# 要删除节点的子树是左子树if parent is None:# 如果父节点为空,说明要删除的是根节点,则直接让根基诶到哪等于它的左子节点self.root = target_node.left# 进一步判断要删除的节点是父节点的左节点还是右节点elif parent.left.value == value:# 要删除的节点是父节点的左节点parent.left = target_node.leftelse:  # 要删除的节点是父节点的右节点parent.right = target_node.leftelse:  # 要删除节点的子树是右子树if parent is None:# 如果父节点为空,说明要删除的是根节点,则直接让根基诶到哪等于它的右子节点self.root = target_node.right# 进一步判断要删除的节点是父节点的左节点还是右节点elif parent.left.value == value:# 要删除的节点是父节点的左节点parent.left = target_node.rightelse:  # 要删除的节点是父节点的右节点parent.right = target_node.right# 测试二叉排序树的创建和遍历
arr = [7, 3, 10, 12, 5, 1, 9, 2]
binary_sort_tree = BinarySortTree()
for i in arr:node = Node(i)binary_sort_tree.add(node)
binary_sort_tree.infix_order()
# 测试删除二叉排序树的结点
binary_sort_tree.delete_node(7)
print("删除节点后:")
binary_sort_tree.infix_order()

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】继承 ⑧ ( 继承 + 组合 模式的类对象 构造函数 和 析构函数 调用规则 )

文章目录 一、继承 组合 模式的类对象 构造函数和析构函数调用规则1、场景说明2、调用规则 二、完整代码示例分析1、代码分析2、代码示例 一、继承 组合 模式的类对象 构造函数和析构函数调用规则 1、场景说明 如果一个类 既 继承了 基类 ,又 在类中 维护了一个 其它类型 的…

找不到conda可执行文件:解决方法

1.在新版本的pycharm出现的问题如下&#xff1a; 2.解决方法: 2.1 将anaconda\Scripts\conda.exe选中 2.2选择自己的anconda自己的环境&#xff0c;之后就可以正常创建conda环境

2023-10-23 LeetCode每日一题(老人的数目)

2023-10-23每日一题 一、题目编号 2678. 老人的数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始的字符串 details 。details 中每个元素都是一位乘客的信息&#xff0c;信息用长度为 15 的字符串表示&#xff0c;表示方式如下&#xff1a; 前十…

橙河网络:国外问卷调查赚钱的项目可靠吗?

国外问卷调查项目是可靠的&#xff0c;是一个长期稳定的互联网项目。 大家好&#xff0c;我是橙河网络&#xff0c;今天聊一聊国外问卷调查赚钱的项目可靠吗&#xff1f; 在海外地区&#xff0c;很多公司和机构&#xff0c;它们为了收集一些关于产品和服务的消费者意见&#…

深入浅出Apache SeaTunnel SQL Server Sink Connector

在大数据时代&#xff0c;数据的迁移和流动已经变得日益重要。为了使数据能够更加高效地从一个源流向另一个目标&#xff0c;我们需要可靠、高效和易于配置的工具。今天&#xff0c;我们将介绍 JDBC SQL Server Sink Connector&#xff0c;这是一个专为 SQL Server 设计的连接器…

MyBatis-Plus实现逻辑删除[MyBatis-Plus系列] - 492篇

历史文章&#xff08;文章累计490&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 M…

【鸿蒙软件开发】文本输入(TextInput/TextArea)

文章目录 前言一、输入框1.1 创建输入框单行输入框多行输入框单行和多行输入框的区别 1.2 设置输入框的类型有哪些类型基本输入模式&#xff08;默认类型&#xff09;密码输入模式 1.3 自定义样式设置无输入时的提示文本设置输入框当前的文本内容。添加backgroundColor改变输入…

MECE分析法

1、前言 前段时间在对项目进行问题分析的时候&#xff0c;领导要求要符合MECE原则&#xff0c;做到逻辑完整而不能遗漏。虽然没听过这个原则&#xff0c;但是总感觉很有道理&#xff08;领导说的都对&#xff09;。于是乎&#xff0c;就找了一些资料了解了一下。 MECE分析法是…

【Rust】4 一文讲解重点 pattern matching | trait | 生命周期 | 闭包 | 迭代器 | 智能指针 | 并发与并行

文章目录 一、pattern matching二、trait2.1 常见 trait2.1.1 Copy 和 Clone2.1.2 PartialEq 和 Eq2.1.3 PartialOrd 和 Ord2.1.4 Hash2.1.5 From, Into, TryFrom, TryInto 2.2 概念2.2.1 关联类型2.2.2 关联常量2.3.3 泛型关联类型2.3.3.1 示例: 用泛型关联类型, 创建集合工厂…

快手进与退,快手董事长在辞任前套现37.78亿港元

快手科技&#xff08;1024.HK&#xff09;在港交所发布公告&#xff0c;宣布自2023年10月29日起&#xff0c;公司创始人宿华将不再担任董事会董事长&#xff0c;而继续担任执行董事和薪酬委员会成员&#xff0c;而他的不同投票权将保持不变。与此同时&#xff0c;快手科技的现任…

爱创科技携手洽洽食品,探索渠道数字化最优解!

坚果的下半场&#xff0c;是从吃到喝。 消费升级大潮下&#xff0c;健康养生理念逐渐深入人心。以“天然健康”为核心的食品新消费潮流正加速形成&#xff0c;一个个打着“美味与营养”黄金设定的品类风口正被不断创建&#xff0c;其中人气有增无减的当属植物基饮品。据相关报告…

【蓝桥杯001】

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;喜欢编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;小新爱学习. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc…

pv操作题目笔记

对于 pv 操作分以下几步走 什么是pv操作 PV操作在进程同步中通常指的是信号量&#xff08;Semaphore&#xff09;操作。信号量是一种用于控制多个并发进程或线程之间的同步和互斥访问的同步工具。PV操作通常涉及两个基本操作&#xff1a;P操作&#xff08;wait操作&#xff0…

024-第三代软件开发-TabView

第三代软件开发-TabView 文章目录 第三代软件开发-TabView项目介绍TabView官方示例 项目实际使用 关键字&#xff1a; Qt、 Qml、 TabView、 关键字4、 关键字5 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Meta-Object Langu…

js如何解决跨域问题?

&#x1f642;博主&#xff1a;锅盖哒 &#x1f642;文章核心&#xff1a;js如何解决跨域问题? 目录 前言&#xff1a;跨域问题的本质 详解&#xff1a;跨域问题的原因和限制 跨域问题的限制包括&#xff1a; 用法&#xff1a;解决跨域问题的方法 1. JSONP&#xff08;J…

Python OpenCV通过灰度平均值进行二值化处理以减少像素误差

Python OpenCV通过灰度平均值进行二值化处理以减少像素误差 前言前提条件相关介绍实验环境通过灰度平均值进行二值化处理以减少像素误差固定阈值二值化代码实现 灰度平均值二值化代码实现 前言 由于本人水平有限&#xff0c;难免出现错漏&#xff0c;敬请批评改正。更多精彩内容…

异步加载 JavaScript

目录 ​编辑 前言&#xff1a;异步加载 JavaScript 的重要性 详解&#xff1a;异步加载 JavaScript 的方法 使用 使用动态创建标签&#xff1a; 使用模块引入&#xff08;ES6模块&#xff09;&#xff1a; 解析&#xff1a;异步加载 JavaScript 的重要性和优势 实践和注…

【C++面向对象】3. 友元函数、友元类

文章目录 【 1. 友元函数 】【 2. 友元类 】 友元可以是一个函数&#xff0c;该函数被称为 友元函数&#xff1b;友元也可以是一个类&#xff0c;该类被称为 友元类。 【 1. 友元函数 】 类的 友元函数是定义在类外部&#xff0c;但有权访问类的所有私有&#xff08;private…

【python入门篇】字符串(4)

这一章节来说下字符串的使用&#xff0c;字符串是 Python 中最常用的数据类型&#xff0c;我们可以使用单引号( &#xff09;或 双引号&#xff08; " )来创建字符串&#xff0c;那么接下来就进入本章节的一个学习。 一、环境配置 我这边python的环境是3.7.8版本的&…

《红蓝攻防对抗实战》四.内网探测协议出网之ICMP协议探测出网

目录 一.Windows系统探测ICMP协议出网 1. Ping命令 2.Tracert 命令 二.Linux系统探测ICMP协议出网 1. Ping命令 ICMP&#xff08;Internet Control Message Protocol&#xff09;是一种面向无连接的协议&#xff0c;属于网络层的协议&#xff0c;用于检测网络通信故障和实…