二叉排序树(BST)

二叉排序树

基本介绍

二叉排序树创建和遍历

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.hqwc.cn/news/145782.html

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

相关文章

PI证书导入总结

当我们在用pi调用https的方式时&#xff0c;接口会报错提示iaik.security.ssl.SSLCertificateException。这需要我们导入对应的证书。 一.下载证书 根据对方提供的url &#xff0c;在浏览器中输入&#xff0c;点击锁头图标&#xff0c;点击证书信息 二.点击详细信息标签&…

Vue单文件组件

一、.vue文件 我们使用Vue的单文件组件的时候&#xff0c;一个.vue文件就是一个组件。 例如我们创建一个School组件&#xff1a; 二、组件的结构 我们编写网页代码的时候有HTML结构、CSS样式、JS交互。 组件里也是同样存在这三种结构的&#xff1a; <template><d…

imu预积分学习(更新中)

imu预积分学习&#xff08;更新中&#xff09; IMU预积分可以做什么&#xff1f; 以上面那个经典图片为例子&#xff0c;IMU可以通过六轴数据&#xff0c;拿到第i帧和第j帧之间的相对位姿&#xff0c;这样不就可以去用来添加约束了吗 但是有一个比较大的问题是&#xff1a; I…

Explainable-ZSL

模型 体会 作者的实验做得很充足&#xff0c;但未提供可直接运行的代码

高等数学啃书汇总重难点(五)定积分

最近都在忙着刷题&#xff0c;尤其是政治和英语也开始加量复习了&#xff0c;该系列断更了将近2个月~不过最近在刷题的时候又遇到一些瓶颈&#xff0c;因此回归基础来整理一下知史点~ 总的来说&#xff0c;虽然第五章也是重中之重&#xff0c;定理数量也很多&#xff0c;但&…

REDIS命令

常见文件名 Redis-cli使用命令 1、启动Redis2、连接Redis3、停止Redis4、发送命令 1、redis-cli带参数运行&#xff0c;如&#xff1a;2、redis-cli不带参数运行&#xff0c;如&#xff1a;5、测试连通性key操作命令 获取所有键查询键是否存在删除键查询键类型移动键查询key的生…

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

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

JAVA基础(JAVA SE)学习笔记(七)面向对象编程(进阶)

前言 1. 学习视频&#xff1a; 尚硅谷Java零基础全套视频教程(宋红康2023版&#xff0c;java入门自学必备)_哔哩哔哩_bilibili 2023最新Java学习路线 - 哔哩哔哩 第二阶段&#xff1a;Java面向对象编程 6.面向对象编程&#xff08;基础&#xff09; 7.面向对象编程&…

Java,回形数

回形数基本思路&#xff1a; 用不同的四个分支分别表示向右向下向左向上&#xff0c;假如i表示数组的行数&#xff0c;j表示数组的列数&#xff0c;向右向左就是控制j的加减&#xff0c;向上向下就是控制i的加减。 class exercise {public static void main(String[] args){//回…

SQL UPDATE 语句(更新表中的记录)

SQL UPDATE 语句 UPDATE 语句用于更新表中已存在的记录。 还可以使用AND或OR运算符组合多个条件。 SQL UPDATE 语法 具有WHERE子句的UPDATE查询的基本语法如下所示&#xff1a; UPDATE table_name SET column1 value1, column2 value2, ... WHERE conditi…

Redis入门概述

Redis入门概述 1.redis是什么 是一种存在内存中的数据库。遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库。并且可以提供提供多种语言的 API。提供了主从模式、Redis Sentinel和Redis Cluster集群架构方案。总结来说redis是基于内存…

pytorch 入门 (三)案例一:mnist手写数字识别

本文为&#x1f517;小白入门Pytorch内部限免文章 &#x1f368; 本文为&#x1f517;小白入门Pytorch中的学习记录博客&#x1f366; 参考文章&#xff1a;【小白入门Pytorch】mnist手写数字识别&#x1f356; 原作者&#xff1a;K同学啊 目录 一、 前期准备1. 设置GPU2. 导入…