数据结构: AVL树
目录
1.AVL树的概念
2.AVL树的模拟实现
AVL树的结构定义
插入
对平衡因子的讨论
旋转
对旋转情况的讨论
1.单旋
1.1左单旋
1.2右单旋
2.双旋
2.1左右双旋
2.2右左双旋
检查是否是AVL树
1.AVL树的概念
当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
- 它的左右子树都是AVL树
- 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
2.AVL树的模拟实现
AVL树的结构定义
节点

AVLTree

插入
插入节点会影响祖先(全部或者部分) ==> 需要更新平衡因子 ==> 讨论是否调整
新增节点的位置进行讨论:
- cur == parent->right parent->bf++
- cur == parent->left parent->bf--
什么决定了是否要继续往上更新爷爷节点, 取决于parent所在的子树高度是否变化? 变了继续更新, 不变则不再更新
- a. parent->bf == 1 || parent->bf == -1 parent所在的子树变了.继续更新, 为什么? ==> 说明插入前parent->bf == 0 , 说明两边高度相等, 现在有一边高1, 说明parent的子一边高一边低, 高度变了.
- b. parent->bf ==2 || parent == -2 -> parent所在的子树不平衡了, 需要处理子树(旋转处理)
- c. parent->bf == 0, parent所在的子树高度不变, 不用继续往上更新, 这一次插入结束. 为什么? ==> 说明插入前parent->bf == 1 or -1 ,说明插入之前一边高一边低, 插入节点填上矮的一边, 它的高度不变.
代码(找到插入的位置):
对平衡因子的讨论

旋转
目的: 1.让子树平衡 2. 降低子树的高度
旋转的原则: 保持它继续是搜索树
对旋转情况的讨论
1.单旋
--细节:
--空节点的处理
--parent需要维护(对parent是否是根节点进行讨论) 处理subR/L
--平衡因子更新
1.1左单旋
parent->_bf == 2 && cur->_bf == 1
--旋转 ==> 处理parent ==>更新平衡因子(parent的parent需要讨论, 影响与subR/L的链接)
代码:
// 左单旋void RotateL(Node* pParent) {Node* subR = pParent->_pRight;Node* subRL = subR->_pLeft;Node* ppnode = pParent->_pParent;//旋转//把subR的左(subRL)给parent的右,parent变为subR的左,并处理它们的parentif (subRL) subRL->_pParent = pParent;pParent->_pRight = subRL;pParent->_pParent = subR;subR->_pLeft = pParent;if (pParent == _pRoot) //根节点{_pRoot = subR;subR->_pParent = nullptr;}else //非根节点{if (ppnode->_pLeft == pParent) {ppnode->_pLeft = subR;}else //ppnode->_pRight == pParent{ppnode->_pRight == subR;}subR->_pParent = ppnode;}//更新平衡因子pParent->_bf = subR->_bf = 0;}
1.2右单旋
parent->_bf == -2 && cur->_bf == -1
代码:
// 右单旋void RotateR(Node* pParent){Node* subL = pParent->_pLeft;Node* subLR = subL->_pRight;Node* ppnode = pParent->_pParent;//旋转//把subL的右(subLR)给parent, parent变为subL的右边, 并处理它们的parentif (subLR) subLR->_pParent = pParent;pParent->_pLeft = subLR;pParent->_pParent = subL;subL->_pRight = pParent;if (pParent == _pRoot) {_pRoot = subL;subL->_pParent = nullptr;}else {if (ppnode->_pLeft == pParent) {ppnode->_pLeft = subL;}else {ppnode->_pRight = subL;}subL->_pParent = ppnode;}//更新平衡因子subL->_bf = pParent->_bf = 0;}
2.双旋
--对单旋的复用 ==> 更新平衡因子
需要保存subRL/LR的平衡因子, 根据插入节点的位置, 进行更新
2.1左右双旋
代码:
// 左右双旋void RotateLR(Node* pParent) {Node* subL = pParent->_pLeft;Node* subLR = subL->_pRight;int bf = subLR->_bf;//旋转RotateL(pParent->_pLeft);RotateR(pParent);//更新平衡因子if (bf == -1) {pParent->_bf = 1;subL->_bf = 0;subLR->_bf = 0;}else if (bf == 1) {pParent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else if (bf == 0) {pParent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}else {assert(false);}}
2.2右左双旋
parent -> bf = 2 && cur -> bf = -1
代码:
// 右左双旋void RotateRL(Node* pParent) {Node* subR = pParent->_pRight;Node* subRL = subR->_pLeft;int bf = subRL->_bf;//右旋RotateR(pParent->_pRight);RotateL(pParent);//讨论平衡因子的更新if (bf == -1) {pParent->_bf = 0;subR->_bf = 1;subRL->_bf = 0;}else if (bf == 1) {pParent->_bf = -1;subR->_bf = 0;subRL->_bf = 0;}else if (bf == 0) {pParent->_bf = 0;subR->_bf = 0;subRL->_bf = 0;}else {assert(false);}}
检查是否是AVL树
1.各子树的高度差是否<=1
2.平衡因子是否正确(右子树-左子树高度判断)
代码:
// AVL树的验证bool IsAVLTree(){return _IsAVLTree(_pRoot);}根据AVL树的概念验证pRoot是否为有效的AVL树bool _IsAVLTree(Node* pRoot) {if (pRoot == nullptr)return true;//1.检查各子树的高度差是否小于1int left_h = _Height(pRoot->_pLeft);int right_h = _Height(pRoot->_pRight);if (right_h - left_h != pRoot->_bf) {cout << "平衡因子异常" << endl;}if (abs(left_h - right_h) > 1)return false;return _IsAVLTree(pRoot->_pLeft) && _IsAVLTree(pRoot->_pRight);}size_t _Height(Node* pRoot) {if (pRoot == nullptr) {return 0;}size_t left_h = _Height(pRoot->_pLeft) + 1;size_t right_h = _Height(pRoot->_pRight) + 1;return left_h > right_h ? left_h : right_h;}
效果:
1.正常情况:
2.屏蔽掉平衡因子的修改:
相关文章:
数据结构: AVL树
目录 1.AVL树的概念 2.AVL树的模拟实现 AVL树的结构定义 插入 对平衡因子的讨论 旋转 对旋转情况的讨论 1.单旋 1.1左单旋 1.2右单旋 2.双旋 2.1左右双旋 2.2右左双旋 检查是否是AVL树 1.AVL树的概念 当向二叉搜索树中插入新结点后,如果能保证每个结点…...
LeetCode-高频 SQL 50 题:连接 篇
目录 1378. 使用唯一标识码替换员工ID 题目描述: SQL语句: 1068. 产品销售分析 I 题目描述: SQL语句: 1581. 进店却未进行过交易的顾客 题目描述: SQL语句: 197. 上升的温度 题目描述࿱…...
操作系统备考学习 day10
操作系统备考学习 day10 第三章 内存管理3.2 虚拟内存管理3.2.1 虚拟内存的基本概念传统存储管理方式的特征、缺点局部性原理虚拟内存的定义和特征如何实现虚拟内存技术 3.2.2 请求分页管理方式页表机制缺页中断机构地址变换机构 3.2.3 页面置换算法最佳置换算法(OP…...
基于侏儒猫鼬优化的BP神经网络(分类应用) - 附代码
基于侏儒猫鼬优化的BP神经网络(分类应用) - 附代码 文章目录 基于侏儒猫鼬优化的BP神经网络(分类应用) - 附代码1.鸢尾花iris数据介绍2.数据集整理3.侏儒猫鼬优化BP神经网络3.1 BP神经网络参数设置3.2 侏儒猫鼬算法应用 4.测试结果…...
ios safari 正则兼容问题
背景: 系统是自己开发的采购管理系统; 最近升级系统之后客户反馈部分苹果手机现在在进入单据界面的时候报错, 内容显示不全; 安卓手机正常; 苹果首页是之前有使用过系统的才不行, 如果是之前没有使用过系统, 现在也是可以(后面查证这一点可能不是很准确, 跟是否等过过系统…...
Win10下基于VS2015编译SQLite3源码
一、下载SQLite SQLite SQLite Download Page 下载红框部分的3个文件 提示:这里有个 sglite-autoconf-3420000.tar.gz 是免编译版,想省事就下载这个,但我自己用这个老是编译不过 所以我这里不推荐这个了 二、配置SQLite 打开vs 2015或者其他…...
Linux 指令学习
Linux 指令学习 以此为记录,也方便自己日后查看回顾! Linux命令基础格式 无论是什么命令,用于什么用途,在Linux中,命令有其通用的格式: command: 命令本身 options:[可选…...
前端渲染后端返回的HTML格式的数据
在日常开发中,经常有需要前端渲染后端返回页面的需求,对于不同数据结构,前端的渲染方式也不尽相同,本文旨在对各种情况进行总结。 后端返回纯html文件格式 数据包含html标签等元素,数据类型如下图: 前端通…...
身份证读卡器ubuntu虚拟机实现RK3399 Arm Linux开发板交叉编译libdonsee.so找不到libusb解决办法
昨天一个客户要在RK3399 Linux开发板上面使用身份证读卡器,由于没有客户的开发板,故只能用本机ubuntu虚拟机来交叉编译,用客户发过来的交叉编译工具,已经编译好libusb然后编译libdonsee.so的时候提示找不到libusb,报错…...
触想五代强固型工业一体机在近海船舶上的应用
1、行业发展背景 近海船舶的发展紧密关联着海上运输、渔业贸易、旅游开发、能源探测等多领域,带动区域经济、文化繁荣发展。 随着现代科学与信息技术在各行各业的作用增强,工业4.0带动的产业升级逐步渗透进船舶领域,在此背景下,船…...
Node-创建Web应用
题记 node创建web应用,以下是所有流程和代码 与php比较:使用 PHP 来编写后端的代码,需要 Apache 或者 Nginx 的 HTTP 服务器,并配上 mod_php5 模块和 php-cgi。 Node应用的组成 node应用由三部分组成: require 指令&a…...
Redis查找并删除key
redis安装在IP为x.x.x.x的服务器上 redis安装 第一步,安装编译工具及库文件。 命令:yum -y install make zlib zlib-devel gcc-c libtool openssl openssl-devel 第二步,下载redis安装包。 命令:cd /usr/local/src wget ht…...
Spring Security认证架构介绍
在之前的Spring Security:总体架构中,我们讲到Spring Security整个架构是通过Bean容器和Servlet容器对过滤器的支持来实现的。我们将从过滤器出发介绍Spring Security的Servlet类型的认证架构。 1.AbstractAuthenticationProcessingFilter AbstractAut…...
提升代码重用性:模板设计模式在实际项目中的应用
在软件开发中,我们经常面临着相似的问题,需要使用相同的解决方法。当我们希望将这种通用的解决方法抽象出来,并在不同的情境中重复使用时,就可以使用设计模式中的模板模式(Template Pattern)。模板模式是一…...
11-k8s-service网络
文章目录 一、网络相关资源介绍二、开启ipvs三、nginx网络示例四、pod之间的访问示例五、service反向代理示例 一、网络相关资源介绍 Servcie介绍 Service是对一组提供相同功能的Pods的抽象,并为它们提供一个统一的入口。借助Service,应用可以方便的实现…...
MyBatisPlus(二十二)代码生成器
使用场景 使用代码生成器,根据数据库表,自动生成对应的 Entity,Mapper,Service,Controller 。 代码 依赖 两个依赖: 生成器依赖模板依赖 <dependency><groupId>com.baomidou</groupId&…...
git报错The project you were looking for could not be found 解决方式
问题描述: 使用git从远程仓库克隆项目到本地的时候。 git clone http://gitlab.com/project/xxxx.git出现这个问题:The project you were looking for could not be found. 原因分析: 你的账号没有项目的权限,你可以在浏览器输…...
“编辑微信小程序与后台数据交互与微信小程序wxs的使用“
引言 在现代移动应用开发中,微信小程序已经成为了一个非常流行和广泛使用的平台。为了使小程序能够展示丰富的内容和实现复杂的功能,与后台数据的交互是至关重要的。同时,微信小程序还提供了一种特殊的脚本语言——wxs,用于增强小…...
从Linux的tty_struct指针获取驱动上下文
背景 问题 前段时间开发一个tty驱动,用途是实现仪器对GPIB消息的接收、处理和上报。对于上报场景,下位机应用将上报内容写入一个驱动创建的tty设备,tty子系统将应用的输入转发给tty驱动,tty驱动将其转换成对SPI从设备࿰…...
PHP WAP餐厅点餐系统mysql数据库web结构apache计算机软件工程网页wamp
一、源码特点 PHP餐厅点餐系统是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 PHP WAP餐厅点餐系统 代码 https://download.csdn.net/download/qq_41221322/88440001 二、…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...









