二叉排序树(BST)

news2024/10/3 18:23:59

二叉排序树

基本介绍

二叉排序树创建和遍历

class Node:
    """
    创建 Node 节点
    """
    value: int = 0
    left = None
    right = None

    def __init__(self, value: int):
        self.value = value

    def add(self, node):
        """
        添加节点
        node 表示要添加的节点
        """
        if node is None:
            return
        # 判断要添加节点和当前子树根节点的大小
        if node.value < self.value:
            # 要添加节点小于当前子树根节点
            if self.left is None:
                # 如果当前子树左子节点为空,则直接将要添加的节点挂在左子节点上
                self.left = node
            else:
                # 否则,递归当前子树的左节点,找到要放置的位置
                self.left.add(node)
        else:  # 要添加节点大于等于当前子树根节点
            if self.right is None:
                # 如果当前子树右子节点为空,则直接将要添加的节点挂在右子节点上
                self.right = node
            else:
                # 否则,递归当前子树的右节点,找到要放置的位置
                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 = None

    def add(self, node: Node):
        """
        添加节点
        node: 要添加的节点
        """
        if self.root is None:
            # 如果根节点为空,直接将新节点当做根节点
            self.root = node
        else:
            # 否则,将新节点放在根节点下
            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 = 0
    left = None
    right = None

    def __init__(self, value: int):
        self.value = value



    def add(self, node):
        """
        添加节点
        node 表示要添加的节点
        """
        if node is None:
            return
        # 判断要添加节点和当前子树根节点的大小
        if node.value < self.value:
            # 要添加节点小于当前子树根节点
            if self.left is None:
                # 如果当前子树左子节点为空,则直接将要添加的节点挂在左子节点上
                self.left = node
            else:
                # 否则,递归当前子树的左节点,找到要放置的位置
                self.left.add(node)
        else:  # 要添加节点大于等于当前子树根节点
            if self.right is None:
                # 如果当前子树右子节点为空,则直接将要添加的节点挂在右子节点上
                self.right = node
            else:
                # 否则,递归当前子树的右节点,找到要放置的位置
                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 self
        elif value < self.value:  # 要删除的值小于当前节点的值,则在当前节点的左子树递归查找
            if self.left:
                return self.left.search_delete(value)
            return None
        else:  # 要删除的值大于当前节点的值,则在当前节点的右子树递归查找
            if self.right:
                return self.right.search_delete(value)
            return None

    def find_parent(self, value: int):
        """
        查找要删除节点的父节点
        :param value: 要删除的节点值
        :return:
        """
        if (self.left and self.left.value == value or
                self.right and self.right.value == value):
            return self
        else:
            # 如果要删除的值小于当前节点的值,且当前节点有左节点,则向左节点递归查找
            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 = None

    def add(self, node: Node):
        """
        添加节点
        node: 要添加的节点
        """
        if self.root is None:
            # 如果根节点为空,直接将新节点当做根节点
            self.root = node
        else:
            # 否则,将新节点放在根节点下
            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 None

    def find_parent(self, value) -> Node:
        """
        查找要删除节点的父节点
        :param value: 要删除节点的值
        :return:
        """
        if self.root:
            return self.root.find_parent(value)
        return None

    def find_and_delete_right_tree_min(self, node: Node) -> int:
        """
        查找以 node 为根节点的二叉排序树的最小节点
        返回小节点的值并从该二叉排序树中删除最小节点
        :param node:
        :return:
        """
        t = node
        while t.left:  # 因为要找最小节点,所以从二叉排序树的左子树中找
            t = t.left
        # 退出循环时,t 指向的就是最小节点
        val = t.value
        self.delete_node(val)
        return val

    def 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}不存在")
            return
        if self.root.left is None and self.root.right is None:
            # 此时找到了要删除的节点,且二叉树只有一个节点,所以要删除的就是这唯一的一个节点
            self.root = None
            return
        # 查找要删除节点的父节点
        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 = None
                return
            if parent.right and parent.right.value == value:
                # 说明要删除节点是父节点的右子节点
                parent.right = None
                return
        elif 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.left
                else:  # 要删除的节点是父节点的右节点
                    parent.right = target_node.left
            else:  # 要删除节点的子树是右子树
                if parent is None:
                    # 如果父节点为空,说明要删除的是根节点,则直接让根基诶到哪等于它的右子节点
                    self.root = target_node.right
                # 进一步判断要删除的节点是父节点的左节点还是右节点
                elif parent.left.value == value:
                    # 要删除的节点是父节点的左节点
                    parent.left = target_node.right
                else:  # 要删除的节点是父节点的右节点
                    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.coloradmin.cn/o/1125223.html

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

相关文章

Your password has expired. To log in you must change it using a client that

早上打开本地mysql链接报错了&#xff0c;提示密码过期 PS:是密码过期&#xff0c;不是密码错误 开始 先看下mysql安装位置 windowsD 打开运行窗口 输入 services.msc 打开服务界面 找到mysql 查看安装路径 windowsD 打开运行窗口 cmd 进入mysql bin 目录 1、cd 你的目…

React 中 keys 的作用是什么?

目录 前言&#xff1a;React 中的 Keys 的重要性 为什么 Keys 重要&#xff1f; 详解&#xff1a;key 属性的基本概念 用法&#xff1a;key 属性的示例 解析&#xff1a;key 属性的优势和局限性 优势&#xff1a; 局限性&#xff1a; key 属性的最佳实践 稳定的唯一标…

ZYNQ linux调试LCD7789

一,硬件管脚 1,参数解释和实物 LVGL是一个开源的图形库,主要用于MCU上屏幕UI的部署,功能完善,封装合理,可裁切性强,也可以实现Linux上fbx的部署。LVGL官网LVGL - Light and Versatile Embedded Graphics Library 每根线的作用

[Linux 基础] make、Makefile自动化构建代码工具

文章目录 1、make与Makefile是什么2、为什么要有make与Makefile3、怎么实现一个Makefile文件3.1 如何编写Makefile文件3.1.1 依赖关系3.1.2 依赖方法 3.2 如何清理项目3.2.1 如何编写3.2.2 clean详解 3.3 make的使用3.4 原理3.4.1 查看文件修改时间 1、make与Makefile是什么 m…

0基础学习VR全景平台篇第110篇:源图像导入和镜头预设 - PTGui Pro教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 本节教程&#xff0c;我们讲述拼接软件 PTGui Pro 操作的第一步&#xff1a;导入源图像和预设镜头&画幅参数。 我们此次课堂有两个重点&#xff1a; 第一点是 培养摄影后期…

拼团小程序制作技巧大揭秘:零基础也能轻松掌握

随着拼团模式的日益流行&#xff0c;越来越多的商家和消费者开始关注拼团小程序的制作。对于没有技术背景的普通人来说&#xff0c;制作一个拼团小程序似乎是一项艰巨的任务。但实际上&#xff0c;选择一个简单易用的第三方平台或工具&#xff0c;可以轻松完成拼团小程序的制作…

024-第三代软件开发-TabView

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

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

开发趋势 Java Lambda 表达式 一&#xff0c;介绍 Java Lambda 表达式是自 Java 8以后引入的一种新的编程特性&#xff0c;它使得 Java 也能使用函数式编程的部分特性。Lambda 表达式提供了一种清晰且简洁的方式来代表一个方法接口&#xff08;single method interface&#x…

【Unity3D日常开发】Unity3D的Color Space(颜色空间)【全解析】

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 Edit→Player Settings→Other Settings→Rendering→Color Sp…

app拉新渠道整合 一手地推、网推拉新平台整理

1.聚量推客 聚量推客自己本身是服务商&#xff0c;自己直营的平台&#xff0c;相对来说数据更好&#xff0c;我们也拿到了平台首码&#xff1a;000000 填这个就行&#xff0c;属于官方渠道 2.蓝猫推客 蓝猫推客我认为是比较又潜力的平台&#xff0c;经过几天测试数据和结算都…

【23级红细胞招新模拟训练(部分题解 不包含最后三题】

前言 提前说明 &#xff1a; 本人是蒟蒻 题解基本没考虑过优化 只求通过 写这篇题解仅仅是分享一下我的做法 使用的语言&#xff1a;cpp 6-1 题目 请编写函数&#xff0c;对三个整数按升序排序。 函数原型 void IntSortAsc3(int *x, int *y, int *z); 说明&#xff1a;参数 …

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

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

基于减法平均优化的BP神经网络(分类应用) - 附代码

基于减法平均优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于减法平均优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.减法平均优化BP神经网络3.1 BP神经网络参数设置3.2 减法平均算法应用 4.测试结果…

二叉树的各类实现判断

如何判断一颗二叉树是否是搜索二叉树&#xff1f; 搜索二叉树 每个子树头节点的左孩子比它小&#xff0c;右孩子比它大 经典的搜索二叉树没有重复的数 判断 将二叉树按照中序遍历&#xff0c;判断是否为升序 1、先将整棵树中序遍历再判断是否升序 //中序遍历public stat…

【STL】priority_queue(优先级队列)详解及仿函数使用(附完整源码)

目录 1. priority_queue介绍和使用1.1 priority_queue介绍1.2 priority_queue使用 2. 仿函数介绍3. priority_queue模拟实现 1. priority_queue介绍和使用 1.1 priority_queue介绍 优先级队列也是在<queue>里&#xff1a; 因此和queue一样&#xff0c;priority_queue也…

java头歌-java中的异常

文章目录 第一关第二关第三关第四关 第一关 第二关 题目要求&#xff1a; public static void main(String[] args) {Scanner sc new Scanner(System.in);try {int num1 sc.nextInt();int num2 sc.nextInt();/********* Begin *********/System.out.println(num1/num2);}…

基于stm32控制的4G模块在设备模式下通讯

这里的32控制其实和51的控制思路都是一样的&#xff0c;都是先利用一个网络助手将家里的无线网生成局域网&#xff0c;接着通过花生壳软件将局域网变成公共网&#xff0c;最后是利用串口助手&#xff0c;在4G模块的AT指令模式写入命令ATSOCKTCPC,公共网IP地址,公共网端口号&…

对话销售易CEO史彦泽:中国SaaS企业,利润和现金流从何而来?

导读&#xff1a;SaaS企业如何快速转身&#xff0c;活下来 “华为应改变思路和经营方针&#xff0c;从追求规模转向追求利润和现金流&#xff0c;保证渡过未来三年的危机。把活下来作为最主要纲领&#xff0c;边缘业务全线收缩和关闭&#xff0c;把寒气传递给每个人。” 2022年…

Pinia入门

1. 什么是Pinia Pinia 是 Vue 的专属的最新状态管理库 &#xff0c;是 Vuex 状态管理工具的替代品 2. 手动添加Pinia到Vue项目 后面在实际开发Vue医疗项目的时候&#xff0c;Pinia可以在项目创建时自动添加&#xff0c;现在我们初次学习&#xff0c;从零开始&#xff1a; …

Object.getPrototypeOf()

1、作用 获取指定对象的原型&#xff08;内部​​[[Prototype]]​​属性的值&#xff09;&#xff0c;如果没有继承属性&#xff0c;则返回 null function Animal() {}var ani new Animal();console.log(ani);console.log(Object.getPrototypeOf(ani));2、注意 在 ES5 中&a…