二叉排序树(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.mzph.cn/news/115896.shtml

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

相关文章

使用序列化技术保存数据 改进 IO流完成项目实战水果库存系统

上一节内容是 使用IO流完成项目实战水果库存系统https://blog.csdn.net/m0_65152767/article/details/133999972?spm1001.2014.3001.5501 package com.csdn.fruit.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java…

Vue单文件组件

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

(十一)Python模块和包

前面章节中&#xff0c;我们已经使用了很多模块&#xff08;如 string、sys、os 等&#xff09;&#xff0c;通过向程序中导入这些模块&#xff0c;我们可以使用很多“现成”的函数实现想要的功能。 那么&#xff0c;模块到底是什么&#xff0c;模块内部到底是什么样子的&…

【网络】HTTPS讲解(侧重于加密、秘钥、证书的讲解)

HTTPS讲解 前言正式开始安全HTTP和HTTPS的关系什么是加密和解密为什么要加密运营商劫持中间人 常⻅的加密⽅式对称加密⾮对称加密 数据摘要数字签名HTTPS 的⼯作过程⽅案 1 - 只使⽤对称加密&#xff08;不可靠&#xff09;⽅案 2 - 只使⽤⾮对称加密&#xff08;不可靠&#x…

js鼠标点击添加图标并获取图标的坐标值

给这个图片添加摄像头图标&#xff0c;并获取图标的坐标值&#xff0c;也就是图标的css样式是positon:absolute,获取left和top的值。 图片1 思路是这样的&#xff0c;获取这里的长度&#xff0c; 图片2 1.鼠标点击时距浏览器的左边距离和上边距离&#xff0c;相当于(0,0)坐标 …

Kotlin函数作为参数指向不同逻辑(二)

Kotlin函数作为参数指向不同逻辑&#xff08;二&#xff09; fun sum(): (Int, Int) -> Int {return { a, b -> (a b) } }fun multiplication(): (Int, Int) -> Int {return { a, b -> (a * b) } }fun math(a: Int, b: Int, foo: (Int, Int) -> Int): Int {ret…

DDOS直接攻击系统资源

DDOS ——直接攻击系统资源 思路&#xff1a; 攻击机利用三次握手机制&#xff0c;产生大量半连接&#xff0c;挤占受害者系统资源&#xff0c;使其无法正常提供服务。 1、先体验下受害者的正常网速。在受害者主机上执行以下命令 (1)开启Apache。 systemctl start apache2 (2…

使用 Requests 库和 PHP 的下载

以下是一个使用 Requests 库和 PHP 的下载器程序&#xff0c;用于从 www.people.com.cn 下载音频。此程序使用了 https://www.duoip.cn/get_proxy 这段代码。 import requests from bs4 import BeautifulSoup import pafy import timedef get_proxy():url "https://www.…

开发趋势 Java Lambda 表达式 第二篇

开发趋势 Java Lambda 表达式 第二篇 Lambda 的发展史 Java Lambda 表达式是在 Java 8 版本中引入的重要特性&#xff0c;它描述了一种更简洁、更灵活的方式来处理函数式编程。 在 Java 8 之前&#xff0c;要实现函数式编程&#xff0c;需要通过匿名类实现接口的方式。这样的…

vue重修之自定义项目、ESLint和代码规范修复

文章目录 VueCli 自定义创建项目ESlint代码规范及手动修复代码规范错误 VueCli 自定义创建项目 安装脚手架 (已安装) npm i vue/cli -g创建项目 vue create xxx选项 Vue CLI v5.0.8 ? Please pick a preset:Default ([Vue 3] babel, eslint)Default ([Vue 2] babel, eslint) …

网安周报|OpenSSF 推出恶意软件包存储库

1.OpenSSF 推出恶意软件包存储库 为了应对恶意开源软件包日益增长的威胁&#xff0c;开源安全基金会 ( OpenSSF ) 推出了一项名为“恶意软件包存储库”的新计划。该存储库可能会成为打击恶意代码的主要参与者&#xff0c;旨在增强开源软件生态系统的安全性和完整性。该存储库已…

软考系列(系统架构师)- 2020年系统架构师软考案例分析考点

试题一 软件架构&#xff08;架构风格、质量属性&#xff09; 【问题1】&#xff08;13分&#xff09; 针对该系统的功能&#xff0c;李工建议采用管道-过滤器&#xff08;pipe and filter)的架构风格&#xff0c;而王工则建议采用仓库&#xff08;reposilory)架构风格。请指出…

C语言文件操作(1)

C语言文件操作&#xff08;1&#xff09; 文章目录 C语言文件操作&#xff08;1&#xff09;一、理解文件1.概述2.分类①.正常角度②.文本文件和二进制文件 二、文件的打开和关闭1.流和标准流2.文件类型指针3.文件的打开和关闭以及使用类型 三、文件缓冲区 一、理解文件 1.概述…

【iOS】JSONModel的基本使用

文章目录 前言一、导入JSONModel二、JSONModel的基本使用1.基本用法2.模型集合3.模型导出为NSDictionary或JSON4.设置所有属性可选&#xff08;所有属性值可以为空&#xff09;5.下划线(蛇式)转驼峰命名法 前言 JSONModel 是一个用于 Objective-C 的开源库&#xff0c;它用于简…

Android View拖拽startDragAndDrop,Kotlin

Android View拖拽startDragAndDrop&#xff0c;Kotlin import android.os.Bundle import android.util.Log import android.view.DragEvent import android.view.View import android.view.View.OnDragListener import android.view.View.OnLongClickListener import android.w…

后台管理系统SQL注入漏洞

对于edu来说&#xff0c;是新人挖洞较好的平台&#xff0c;本次记录一次走运的捡漏0x01 前景 在进行fofa盲打站点的时候&#xff0c;来到了一个后台管理处看到集市二字&#xff0c;应该是edu站点 确认目标身份&#xff08;使用的quake进行然后去ipc备案查询&#xff09; 网…

寻找二叉树一个节点的后继节点

后继节点&#xff1a;中序遍历的后一个节点 普通二叉树&#xff1a;中序遍历得到一个list&#xff0c;时间复杂度O(n) 本题的二叉树&#xff1a;有父节点的指针&#xff0c;后继节点与原节点的距离为1&#xff0c;因此可以直接通过父节点找到下一个节点 优化&#xff1a;节点…

Mac 开机提示Google LLC 注册 无法登录进入系统

Google LLC 会在电脑启动时提示如下弹窗&#xff0c;并要求登录谷歌账户进行验证 此时很明显没有用来进行验证的账号&#xff0c;所以需要关掉这个验证程序 从日志里面可以看到LLC启动了一个Tiny.app的程序 只需要想办法把这个程序删掉即可 关机 按住 Command R 开机 进入R…

Openssl数据安全传输平台004:Socket C-API封装为C++类 / 服务端及客户端代码框架和实现

文章目录 0. 代码仓库1. 客户端C API2. 客户端C API的封装分析2.1 sckClient_init()和sckClient_destroy()2.2 sckClient_connect2.3 sckClient_closeconn()2.4 sckClient_send()2.5 sckClient_rev()2.6 sck_FreeMem 3. 客户端C API4. 服务端C API5. 服务端C6. 客户端和服务端代…

【MySQL架构篇】MySQL字符集、大小写规范及默认数据库

文章目录 1. 字符集与字符集比较规则2. 大小写规范3. 默认数据库4. 与文件系统相关 1. 字符集与字符集比较规则 MySQL有4个级别的字符集和比较规则&#xff0c;分别是 服务器级别数据库级别表级别列级别 当创建对应表或列未指定字符集时&#xff0c;默认会取其上一级别的字符…