AVL树左旋转算法思路与图解

news2024/11/30 0:41:25

AVL树左旋转算法思路与图解

对于数列{4, 3, 6, 5, 7, 8}, 当我们插入8的时候, rightHeight() - leftHeight() > 1成立(也就是当前AVL树中的根节点的BF(平衡因子)> 1了), 此时这个AVL树已经不再是平衡的了, 也就是已经不是一个AVL树了, 所以我们要经过处理之后让其重新平衡

  • 那么要如何处理?

    • 其实很简单, 当我们构建了这个树之后我们可以发现此时图中的最小不平衡子树是一个RR型最小不平衡子树, 所以我们只需要对最小不平衡子树的根节点执行一个左旋的操作即可

那么如何实现左旋转? —> 此时我们先使用图解的方式来进行演示:

在这里插入图片描述

那么我们具体是如何实现对最小生成树根节点的左旋转的?

  1. 创建一个新的结点newNode(以旧根节点的值来创建, 在上图中为旧根结点的值为4)
  2. 把新结点的左子树设置为旧根节点的左子树
  3. 把新结点的右子树设置为旧根结点的右子树的左子树
  4. 把旧根结点的值修改为新根节点的值(在左旋中就是把旧根结点的值替换为其右子节点的值)
    • 左旋转时旧根结点的右子节点的值就是新根节点值
  5. 因为此时旧根结点的值已经被更新为新根节点的值, 所以我们要将原本的存储新根结点值的结点从树上删去 —> 我们让更新值之后的根节点的右子结点指向其右子结点的右子树, 这样就能删除掉原本存储新根节点值的结点
    • 这个时候其实我们就是没有引用指向图中的⑥号结点, 那么这个节点最终就会被Java的垃圾回收机制回收掉
  6. 更新之后的根节点的左子树指向新的结点newNode
其实上面我们可以发现插入8是插入在了最小不平衡子树的根节点的右子树上, 我们将这种情况导致的不平衡称之为: RR型最小不平衡子树, 我们对于RR型最小不平衡子树的平衡化就是对RR型最小不平衡子树的根节点执行一个左旋转即可

我们的左旋转算法的核心其实只有两步:

  1. 原本旧根结点成为为现在新根结点的左子树
  2. 原本新根结点的左子树成为现在旧根节点的右子树
其实上面的六步就是这里核心的实现(我们一定要将这两部核心记住, 至于具体的如何实现我们可以有不同的实现, 但是上面的实现是我们比较推荐的实现方式)

补充:

我们最终左旋的操作肯定是在添加元素的操作中实现的, 由于我们的添加元素的操作是递归实现的, 在添加完元素之后就要开始回溯了, 而在回溯的时候我们就要判断回溯到的结点的BF(平衡因子)是否大于1, 如果大于1, 这个时候就说明以此结点为根的结点是此时不平衡树的最小不平衡子树, 所以我们再判断如果这个最小不平衡子树是一个RR型的, 那么我们就执行对应的左旋转操作即可

  • 那么这时候可能有的人会问: 那么我们的旋转操作此时是在递归中执行的, 那么我们的不平衡子树中不仅仅是有最小不平衡子树, 可能还会有其他的不平衡子树,那么当我们对最小不平衡子树执行完旋转的操作之后会不会还会对其他的不平衡子树执行旋转的操作? ,我们按理说只需要对最小不平衡子树执行旋转操作, 执行多个旋转操作不就发生了错误?
    • 这个时候注意: 当我们第一次回溯到最小不平衡子树的根节点之后, 我们对这个最小不平衡子树执行了响应的旋转操作之后我们的整个树就重新是一个平衡树了, 所以即使我们的旋转的操作是在递归中进行调用的, 但是最终我们的旋转操作只会在回溯到最小生成树的根节点的时候执行一次而已

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

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

相关文章

【C】输入一行字符,分别统计出其中英文字母、数字、空格和其他字符的个数

C语言没有字符串形式&#xff0c;所以可以用 char[] 数组来代替&#xff0c;但需要指定分配空间&#xff0c;所以可以采用单字符读取的形式&#xff1a; #include<stdio.h> int main(){char ch;int space0,number0,character0,other0;chgetchar(); …

WSO2安装使用的全过程详解

WSO2安装使用的全过程详解1. Install1.1 Docker Install 1.2 Uninstall2. User Guide3. Big Data -- Postgres4. Awakening1. Install 1.1 Docker Install 显示镜像 docker images/docker image ls拉去镜像/版本 docker pull wso2/wso2am 1.2 Uninstall 查看正在运行的容器 d…

流体动力润滑(轴承油膜承载机理)

目录 1.流体动力润滑 2.流体动力润滑的应用&#xff1a;楔形效应承载机理 3.承载量的计算 4.轴承动压油膜 1.流体动力润滑 定义&#xff1a;两个相对运动物体的摩擦表面&#xff0c;用于借助相对速度而产生的黏性流体膜将两摩擦面完全隔离开&#xff0c;由流体膜产生的压力…

那些下载不了的视频,Python只用1行代码就能直接下载

前言 现在有很多网站都并不支持直接下载的&#xff0c;例如我们常去的B站里面的视频&#xff0c;在页面是没有下载按钮的&#xff0c;还有的视频需要我们下载客户端才能下载…虽然这并不能拦住多少人&#xff0c;有些聪明的小伙伴就会去下载一些第三方软件去下载&#xff0c;比…

apache-atlas-hbase-bridge-源码分析

元数据类型 Hbase元数据类型, 包括命令空间、表、列族、列 public enum HBaseDataTypes {// ClassesHBASE_NAMESPACE,HBASE_TABLE,HBASE_COLUMN_FAMILY,HBASE_COLUMN;public String getName() {return name().toLowerCase();} }Hbase元数据采集实现 1&#xff09;批量采集HBa…

MyBatis基于XML的使用——缓存

1、介绍 MyBatis 内置了一个强大的事务性查询缓存机制&#xff0c;它可以非常方便地 配置和定制。 为了使它更加强大而且易于配置&#xff0c;我们对 MyBatis 3 中的缓存实现进行了许多改进。 默认情况下&#xff0c;只启用了本地的会话缓存&#xff0c;它仅仅对一个会话中的数…

【Java】异常处理

异常本质上是程序上的错误&#xff0c;包括程序逻辑错误和系统错误。比如使用空的引用、数组下标越界、内存溢出错误等. 错误在我们编写程序的过程中会经常发生&#xff0c;包括编译期间和运行期间的错误&#xff0c;在编译期间出现的错误有编译器帮助我们一起修正&#xff0c;…

使用java代码向mysql数据库插入100万条数据

使用java代码向mysql数据库插入100万条数据 使用springboot集成Mysql数据库&#xff0c;并使用java代码循环向msql数据库插入100万条数据&#xff0c;并测试插入时间 目录结构使用java代码向mysql数据库插入100万条数据一、使用工具二、项目结构图创建springboot项目启动类创建…

高并发-防止雪崩与穿透

一、DB查询前加锁 /** * 本地堆内缓存&#xff0c;优先级最高 */ ON_HEAP(1), /** * 本地堆外缓存&#xff0c;不影响GC&#xff0c;可以管理比堆内缓存更多的数据 * 数据get/set涉及序列化&#xff0c;性能次于本地堆内缓存 */ OFF_HE…

手撕红黑树

目录 一、概念 二、红黑树的插入操作 第一步: 按照二叉搜索树的规则插入新节点 第二步: 插入后检测性质是否造到破坏&#xff0c;若遭到破坏则进行调整 情况一: cur为红&#xff0c;parent为红&#xff0c;grandfather为黑&#xff0c;uncle存在且为红 情况二: cur为红&a…

JLink 添加新设备用于下载/调试固件

新驱动的安装目录结构如下&#xff1a; 可以看出新版本的 JLink 驱动中已经没有 Devices 目录和 JLinkDevices.xml 文件了&#xff0c;即旧的方法已经不能在新的驱动中使用了。 如果需要继续使用旧的方式添加新设备&#xff0c;则需要下载 JLink_V770d 之前的版本。 在新驱动…

若依框架解读(微服务版)—— 4.认证,登出(Gateway网关)

认证 我们可以查看token值 我们进入授权中心&#xff0c;这里其他的解析解析token的步骤与上一篇文章中的生成token是逆操作&#xff0c;也比较简单。我们进入ignoreWhite.getWhites()方法 此处的两个注解是获取nacos当中的白名单&#xff0c;我们打开nacos&#xff0c;进入网关…

Shell程序退出状态码的命令详解

在本篇文章当中主要给大家介绍了一些常见的程序退出的状态码&#xff01;并且给出一下例子帮助大家仔细理解&#xff0c;并且使用C语言和python语言实现获取子进程退出时候的退出状态码。 程序退出状态码 前言 在本篇文章当中主要给大家介绍一个shell的小知识——状态码。这是…

Object.defineProperty用法

Object.defineProperty() 定义新属性和修改原有的属性 Object.defineProperty( obj&#xff0c;prop,descriptor) 翻译&#xff1a;对象.定义属性&#xff08;对象&#xff0c;属性名必须是字符写法&#xff0c;{ value:所有 }&#xff09; 创建一个对象&#xff1a; var o…

OSI七层参考模型和TCP/IP四层(五层)参考模型

OSI七层参考模型 OSI&#xff08;OSI&#xff0c;Open System Interconnection&#xff09;七层模型&#xff0c;是参考模型是国际标准化组织&#xff08;ISO&#xff09;制定的一个用于计算机或通信系统间互联的标准体系。它是一个七层的、抽象的模型体&#xff0c;不仅…

泰勒展开式

泰勒展开式 文章目录泰勒展开式简介定义近似举例推导理解参考简介 泰勒公式&#xff0c;也称泰勒展开式&#xff0c;可以用来在局部范围内近似复杂函数。 通俗的讲&#xff1a; 设有一个复杂的未知函数f(x)f(x)f(x)&#xff0c;我们想要知道它在某个范围[a,b][a,b][a,b]内的值…

抽象工厂模式

思考抽象工厂模式 抽象工厂专注于产品簇的实现&#xff0c;主要是那些有关联关系的&#xff0c;如果只有一个产品的话就退化成了工厂方法模式 1.抽象工厂模式的本质 抽象工厂模式的本质:选择产品簇的实现。 产品簇&#xff08;Product family&#xff09;指具有相同或相似的功能…

Simulink电机控制代码生成-----关于PI控制器参数整定的一点总结

目录 PI控制器的参数整定方法 方法一&#xff1a; 方法二&#xff1a; 方法对比 总结 看过很多论文&#xff0c;对PI参数的整定方法五花八门&#xff0c;还有PI参数整定的口诀&#xff0c;所谓口诀就是试凑法。除了试凑法&#xff0c;本文提供另外两种方法来整定PI参数&am…

【JavaSE】类与对象--封装性

文章目录一、面向对象的三大特性二、封装性1.什么是封装性&#xff1f;2.为什么要有封装性&#xff1f;3.封装性的作用4.封装性的实现步骤5.访问限定修饰符一、面向对象的三大特性 面向对象的三个基本特征是&#xff1a;封装、继承、多态。 二、封装性 1.什么是封装性&#xf…

BLE学习(4):蓝牙地址类型和设备的隐私

蓝牙地址也被称为蓝牙MAC地址&#xff0c;它能唯一标识一个蓝牙设备的48位的值。在蓝牙规范中&#xff0c;它被称为BD_ADDR。蓝牙的地址类型可以分为两种&#xff1a;public addresses和random addresses&#xff0c;其中random addresses又可再细分为几类&#xff0c;如下图所…