平衡二叉树(AVL)python实现

2023-11-06

AVL树是一种特殊的二叉搜索树 (BST树),数据极端情况下, 二叉搜索树会退化成为单链表,但是AVL树通过旋转操作规避了这个问题。

查找平均复杂度:O(logn)

# AVL树不适于删除的情况
class AVLTreeNode(object):
    def __init__(self, data):
        self.data = data  # 数据
        self.left: AVLTreeNode = None  # 左子树
        self.right: AVLTreeNode = None  # 右子树
        self.height = 1  # 树高度


def get_data(node: AVLTreeNode):
    return node.data


def set_data(node: AVLTreeNode, data):
    node.data = data


# 获得树形结构
def get_left_node(node: AVLTreeNode):
    return node.left


def get_right_node(node: AVLTreeNode):
    return node.right


def get_height(node: AVLTreeNode):
    if node is None:
        return 0
    return node.height


def get_max_node(node: AVLTreeNode):
    temp_node = node
    if temp_node.right is not None:
        return get_max_node(temp_node.right)
    else:
        return temp_node


def get_min_node(node: AVLTreeNode):
    temp_node = node
    if temp_node.left is not None:
        return get_min_node(temp_node.left)
    else:
        return temp_node


def get_node(node: AVLTreeNode, data):
    temp_node: AVLTreeNode = node
    while temp_node:
        if data < temp_node.data:
            temp_node = temp_node.left
        elif data > temp_node.data:
            temp_node = temp_node.right
        else:
            return temp_node
    return None


# 右旋:先记录待旋转节点的左节点,然后将左节点的right指向待旋转节点即可
def right_rotate(node: AVLTreeNode):
    head_node: AVLTreeNode = node.left
    node.left = head_node.right  # 将父节点的右侧放在待旋转节点的左侧
    head_node.right = node  # 将父节点的右指针指向待旋转节点
    node.height = max(get_height(node.left), get_height(node.right)) + 1
    head_node.height = max(get_height(head_node.left), get_height(head_node.right)) + 1
    return head_node


def left_rotate(node: AVLTreeNode):
    head_node: AVLTreeNode = node.right
    node.right = head_node.left
    head_node.left = node
    node.height = max(get_height(node.left), get_height(node.right)) + 1
    head_node.height = max(get_height(head_node.left), get_height(head_node.right)) + 1
    return head_node


# 先左旋,再右旋
def left_right_rotate(node: AVLTreeNode):
    son_node = left_rotate(node.left)
    node.left = son_node
    return right_rotate(node)


def right_left_rotate(node: AVLTreeNode):
    son_node = right_rotate(node.right)
    node.right = son_node
    return left_rotate(node)


# 左子树与右子树差距最大为1,否则及时调整
def adjust_height(node: AVLTreeNode):
    if get_height(node.right) - get_height(node.left) > 1:
        if get_height(node.right.right) > get_height(node.right.left):
            node = left_rotate(node)
        else:
            node = right_left_rotate(node)
    elif get_height(node.left) - get_height(node.right) > 1:
        if get_height(node.left.left) > get_height(node.left.right):
            node = right_rotate(node)
        else:
            node = left_right_rotate(node)
    else:
        pass
    return node


def insert_node(node: AVLTreeNode, data):
    if node is None:
        return AVLTreeNode(data)
    if (node.data is not None) and (data < node.data):  # 向左插入
        node.left = insert_node(node.left, data)
        node.height = max(get_height(node.left), get_height(node.right)) + 1
        node = adjust_height(node)
    elif (node.data is not None) and (data > node.data):  # 向右插入
        node.right = insert_node(node.right, data)
        node.height = max(get_height(node.left), get_height(node.right)) + 1
        node = adjust_height(node)
    else:
        print('Can not insert same value')
    return node


def delete_node(node: AVLTreeNode, data):
    if node is None:
        return None
    if (node is not None) and (data < node.data):  # 左侧查询
        node.left = delete_node(node.left, data)
        node = adjust_height(node)
    elif (node is not None) and (data > node.data):  # 右侧查询
        node.right = delete_node(node.right, data)
        node = adjust_height(node)
    else:  # 在这里删除
        if (node.left is not None) and (node.right is not None):  # 左右节点都不为空
            node.data = get_min_node(node.right).data
            node.right = delete_node(node.right, node.data)
        elif node.left is not None:  # 左节点不为空,右节点为空
            node = node.left
        else:  # 左节点为空,右节点未知
            node = node.right
    if node is not None:
        node.height = max(get_height(node.left), get_height(node.right)) + 1
        adjust_height(node)
    return node


def get_all(node: AVLTreeNode):
    values = []

    def add_values(values, node: AVLTreeNode):
        if node is not None:
            values = add_values(values, node.left)
            values.append(node.data)
            values = add_values(values, node.right)
        return values

    return add_values(values, node)


def main():
    root = AVLTreeNode(10)
    number_list = (3, 2, 1, 4, 5, 6, 7, 15, 26, 17)
    for number in number_list:
        root = insert_node(root, number)
    all_values = get_all(root)
    del_note = delete_node(root, 3)
    all_values = get_all(root)
    pass


if __name__ == '__main__':
    main()

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

平衡二叉树(AVL)python实现 的相关文章

  • 具有多个输入的kerasvalidation_data

    我尝试使用validation data方法 但是有问题 model fit X macd train X rsi train X ema train Y train sample weight sample weight validati
  • 当默认 pip 为 pip2 时,升级 pip3 的正确格式是什么?

    我为两者开发Python 2 and 3 因此 我必须同时使用pip2 and pip3 使用时pip3 我收到此升级请求 最后两行 pip3 install arrow Requirement already satisfied use
  • 如何从 Python 返回 JSON 值?

    我从如下所示的 jQuery 文件发送 ajax 请求 该请求需要 JSON 格式的响应 jQuery ajax url Control getImageDetails file id currentId type GET contentT
  • 如何跳过财务图中的空日期(周末)

    ax plot date dates dates highs lows 我目前正在使用此命令来绘制财务高点和低点Matplotlib http en wikipedia org wiki Matplotlib 效果很好 但如何删除 x 轴上
  • 是否可以在 Sphinx 中隐藏 Python 函数参数?

    假设我有以下函数 该函数记录在Numpydoc 风格 https github com numpy numpy blob master doc HOWTO DOCUMENT rst txt 并且文档是自动生成的Sphinx http sph
  • 如何使用 boto3 从 AWS Cognito 获取经过身份验证的身份响应

    我想使用 boto3 获取访问 AWS 服务的临时凭证 用例是这样的 我的 Cognito 用户池中的用户登录到我的服务器 我希望服务器代码为该用户提供访问其他 AWS 服务的临时凭证 我有一个存储我的用户的 Cognito 用户池 我有一
  • 检查多维 numpy 数组的所有边是否都是零数组

    n 维数组有 2n 个边 1 维数组有 2 个端点 2 维数组有 4 个边或边 3 维数组有 6 个 2 维面 4 维数组有 8 个边 ETC 这类似于抽象 n 维立方体发生的情况 我想检查 n 维数组的所有边是否仅由零组成 以下是边由零组
  • __getitem__、__setitem__ 如何处理切片?

    我正在运行 Python 2 7 10 我需要拦截列表中的更改 我所说的 更改 是指在浅层意义上修改列表的任何内容 如果列表由相同顺序的相同对象组成 则列表不会更改 无论这些对象的状态如何 否则 它会更改 我不需要找出来how列表已经改变
  • 为什么我不能“string”.print()?

    我的理解print 在 Python 和 Ruby 以及其他语言 中 它是字符串 或其他类型 上的方法 因为它的语法非常常用 打印 嗨 works 那么为什么不呢 hi print 在 Python 中或 hi print在红宝石工作 当你
  • 将分布拟合到直方图

    I want to know the distribution of my data points so first I plotted the histogram of my data My histogram looks like th
  • 为什么我在将数据上传到数据库时不断看到“正在重置断开的连接”?

    我正在通过 REST API 将数亿个项目从 Heroku 上的云服务器上传到 AWS EC2 中的数据库 我正在使用 Python 并且经常在日志中看到以下 INFO 日志消息 requests packages urllib3 conn
  • 如何在返回的 AJAX 调用上使用 django 模板标签?

    我有一个简单的 AJAX 脚本 它在名为的搜索字段中获取输入的字符串AJAXBox并调用一个视图函数 该函数使用过滤器查询数据库并返回与输入参数匹配的所有 User 对象的查询集 当我使用 django 模板标签迭代查询集时 它不起作用 我
  • Microsoft Azure 数据仓库和 SqlAlchemy

    我正在尝试使用 python 的 sqlalchemy 库连接到 microsoft azure 数据仓库 并收到以下错误 pyodbc Error HY000 HY000 Microsoft ODBC SQL Server Driver
  • 将查询参数添加到 URL

    我正在尝试自动从网站下载数据 我需要将动态参数传递到每天更改的站点 html 的结构是表格而不是表单 如何传递参数并从 url 获取结果 这是我尝试过的 它需要在 python 2 7 中 import urllib url https d
  • 将 for 循环替换为 pyspark 中的并行进程

    我在脚本中使用 for 循环来为 size DF 数据帧 的每个元素调用函数 但这需要很多时间 我尝试通过地图删除 for 循环 但没有得到任何输出 size DF 是我从表中获取的大约 300 个元素的列表 用于 import call
  • Bottle 是否可以处理没有并发的请求?

    起初 我认为 Bottle 会并发处理请求 所以我编写了如下测试代码 import json from bottle import Bottle run request response get post import time app B
  • Python Flask应用程序无法被网络中的远程计算机访问

    我在本地主机上的 python 上运行了一个简单的 Flask Web 应用程序 Web 应用程序在 127 0 0 1 8000 上运行 但我无法使用 myHostComputerIPaddress 8000 从网络中的远程计算机访问它
  • 在Python中将罗马数字转换为整数

    根据 user2486 所说 这是我当前的代码 def romanMap map M 1000 CM 900 D 500 CD 400 C 100 XC 90 L 50 XL 40 X 10 IX 9 V 5 V 4 I 1 return
  • 在Python中打开网站框架或图像

    所以我对 python 相当熟练 并且经常使用 urllib2 和 Cookies 来实现网站自动化 我刚刚偶然发现了 webbrowser 模块 它可以在默认浏览器中打开一个网址 我想知道是否可以从该 url 中仅选择一个对象并打开它 具
  • 将自定义属性添加到 Tk 小部件

    我的主要目标是向小部件添加隐藏标签或字符串之类的内容 以在其上保存简短信息 我想到创建一个新的自定义 Button 类 在本例中我需要按钮 它继承所有旧选项 这是代码 form tkinter import class NButton Bu

随机推荐

  • 毕业设计-基于机器视觉的焊缝图像处理研究- OpenCV

    目录 前言 课题背景和意义 实现技术思路 一 焊缝识别系统设计 二 焊缝图像预处理 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几年各个学校要
  • 设置读取plc时间_Visual Studio 2010-C#跟西门子1200(Sharp7)窗体控制④-循环读取

    Visual Studio 2010 C 跟西门子1200 Sharp7 窗体控制 循环读取 上期回顾 上期主要是对单个按钮 按下后能够同时置位PLC的多个位 本期做一个读取PLC的OK NOK的统计数据的C 标签 先创建一个标签 在设定一
  • SpringBoot:@Schedule定时任务

    一 Schedule SpringBoot内置了Sping Schedule定时框架 通过注解驱动方式添加所注解方法到定时任务 根据配置定时信息定时执行 二 定时任务实现 1 开启定时任务 package com gupao springb
  • 使用VBA在工作表中快速插入行

    在工作表中插入行 有需要用到代码吗 是不是杀鸡用牛刀的感觉 其实不是这样的 在很多复杂的应用场景中 插入行不再是简单的单击鼠标右键就可以即刻完成的 比如需要隔行插入空行 如果有一万行数据 是不是搞到手抽筋了 再比如插入空行的数量不是固定的
  • 自动记录数据录入时间不懂得VBA的朋友可以看看

    在日常工作中 经常会遇到需要实时记录数据录入的时间问题 有朋友会说了 用快捷键啊 按Ctrl 分号 可以返回当前的系统日期 按Ctrl Shift 分号 可以返回当前的系统时间 但是如果需要同时返回日期和时间又该怎么处理呢 对于懂得VBA的
  • 关于对Vue中slot插槽理解

    关于slot插槽理解 1 何时需要使用插槽 在开发中 我们需要将共性内容抽取到组件中 将不同的暴露为插槽 插槽的益处便是 一旦预留了插槽 使用者便可以根据自己的需求来决定插槽中插入的的内容 2 slot的基本使用 div div
  • 软件测试之网络协议基础

    软件测试之网络协议基础 前言 我会在此账号上持续更新 软件测试的文章 包括网络部分 前端代码部分 数据库部分 软件测试部分 互联网协议 osi 7层协议 tcp ip 5层协议 网络协议的存在是为了两者中间根据一定的协议沟通交流 每层运行常
  • 光线跟踪(RayTracing)原理及c++实现

    Chapt1 Why to write a RayTracing Render 提到Computer Graphics 众所周知的是如OpenGL Direct3D这样非常流行的光栅化渲染器 事实上 这些大部分应用于游戏制作的API主要为实
  • Flutter控件——布局控件:层叠

    Stack 层叠布局 Android 中的 Frame 布局是相似的 子组件可以根据距父容器四个角的位置来确定自身的位置 层叠布局允许子组件按照代码中声明的顺序堆叠起来 Flutter中使用Stack和Positioned这两个组件来配合实
  • 怎么关闭win10虚拟机服务器,win10系统彻底关闭退出vmware虚拟机的步骤

    有关win10系统彻底关闭退出vmware虚拟机的操作方法想必大家有所耳闻 但是能够对win10系统彻底关闭退出vmware虚拟机进行实际操作的人却不多 其实解决win10系统彻底关闭退出vmware虚拟机的问题也不是难事 小编这里提示两点
  • 数十万条以上的大量数据如何快速插入数据库中

    引言 这几天工作这边同事遇到了一个问题 对十五万条数据进行计算 插入数据库的时候耗时很严重 使用了批量插入对十五万条数据插入仍然耗费了30秒 前面计算也耗费了二十多秒 系统流畅度因此很难堪 经过我的排查发现主要是两个点需要优化 1 计算的算
  • 关于STM32在线升级文件大或者跳转后中断有问题的解决方法(IAR环境)

    首先 大家都知道是跳转到每个程序的复位中断地址 一开始我的IAR环境的启动文件是没有复位中断地址的 可以去IAR官网随便下载一个重新覆盖掉启动文件 当然还得看你的外设中断有没有包含 或者有多的要去掉 DCD Handler类型的 如果遇到I
  • 怎样在 Markdown 中使程序代码带上行号

    在图灵社区使用 Markdown 写文章时 如果在一段文字的每行开头加上四个空格 或者一个制表符 Tab 这段文字就会被视为程序代码 这样 就会自动识别所用的编程语言 进行代码染色 语法高亮显示 但是 如果这段程序很长的话 就有两个小问题
  • 假设检验,显著性,置信水平,p值,点估计

    1 为什么需要假设检验 以下图激光器项目为例子 抽样30个 改善前720mw 改善后723mw 有一点提升 提升小 可能是正常的波动 所以不一定真的提升了 所以到底是正常波动还是真的改善了 需要结合功率标准差进行分析 标准差决定了波动的情况
  • 医疗管理系统-图形报表、POI报表

    目录 1 套餐预约占比饼形图 1 1 需求分析 1 2 完善页面 1 2 1 导入ECharts库 1 2 2 参照官方实例导入饼形图 1 3 后台代码 1 3 1 Controller 1 3 2 服务接口 1 3 3 服务实现类 1 3
  • STM8 学习笔记 5:时钟

    1 概述 时钟是单片机的脉搏 是单片机的驱动源 使用任何一个外设都必须打开相应的时钟 这样的好处是 如果不使用一个外设的时候 就把它的时钟关掉 从而可以降低系统的功耗 达到节能 实现低功耗的效果 每个时钟tick 系统都会处理一步数据 这样
  • 图数据库-Neo4j:linux centOS7安装

    1 下载 下载地址 社区版免费 https neo4j com download other releases releases 2 解压 tar axvf neo4j community 3 4 5 unix tar gz 3 修改配置文
  • 完全图解自然语言处理中的Transformer——BERT基础(入门长文)

    翻译自Jay Alammar Blog 在上一篇文章可视化Seq2Seq attention中 我们介绍了现在深度学习中特别常用的Attention 注意力 机制 注意力可以提升机器翻译的效果 这篇文章介绍Transformer 一种使用注
  • 深入理解Netty高性能网络框架

    大家好 今天我们来聊聊Netty的那些事儿 我们都知道Netty是一个高性能异步事件驱动的网络框架 它的设计异常优雅简洁 扩展性高 稳定性强 拥有非常详细完整的用户文档 同时内置了很多非常有用的模块基本上做到了开箱即用 用户只需要编写短短几
  • 平衡二叉树(AVL)python实现

    AVL树是一种特殊的二叉搜索树 BST树 数据极端情况下 二叉搜索树会退化成为单链表 但是AVL树通过旋转操作规避了这个问题 查找平均复杂度 O logn AVL树不适于删除的情况 class AVLTreeNode object def