当前位置: 首页 > news >正文

C++进阶之AVL树

个人主页:点我进入主页

专栏分类:C语言初阶  C语言进阶  数据结构初阶    Linux    C++初阶     C++进阶​    ​​​​算法

欢迎大家点赞,评论,收藏。

一起努力,一起奔赴大厂

目录

一.前言

二.插入

三.旋转 

3.1右旋

3.2左旋

3.3左右双旋

3.4右左双旋

四.测试


一.前言

        在看这篇博客之前需要了解二叉搜索树的相关内容,可以看这篇博客二叉搜索树,AVL树可以看成为了解决二叉搜索树的问题,它保证了左右子树高度差不超过1。本次的内容的重点就是对AVL树的旋转。

二.插入

        AVL树的插入规则和二叉搜索树的插入规则类似,左子树都小于父节点,右子树都大于父节点,在这里我们引入了一个平衡因子,我们先插入后然后进行调节平衡因子,平衡因子的计算=右子树的高度-左子树的高度,插入的新节点的平衡因子为0,当插入的节点在父节点的右边,父节点的平衡因子+1,当插入的节点在父节点的左边,父节点的平衡因子-1,当整后父节点的平衡因子为0时直接结束,不需要继续调整,当调整后父节点的平衡因子为+1或者-1时需要继续向上进行调整,当调整后父节点的平衡因子为+2或-2时需要进行旋转。我们看下面的代码实现:

bool insert(const pair<K, V>& kv)
{Node* newnode = new Node(kv);if (_root == nullptr) _root = newnode;else{Node* cur = _root, * parent = nullptr;while (cur){if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}else if (kv.first > cur->_kv.first) {parent = cur;cur = cur->_right;}else  return false;}if (kv.first < parent->_kv.first) parent->_left = newnode;else parent->_right = newnode;newnode->_parent = parent;//调整平衡因子while (parent){if (newnode == parent->_left) parent->_bf--;else parent->_bf++;if (parent->_bf == 0) break;else if (parent->_bf == 1 || parent->_bf == -1){newnode = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){if (parent->_bf == 2 && newnode->_bf == 1){RatoteL(parent);}else if (parent->_bf == -2 && newnode->_bf == -1){RatoteR(parent);}else if (parent->_bf == 2 && newnode->_bf == -1){RatoteRL(parent);}else if (parent->_bf == -2 && newnode->_bf == 1){RatoteLR(parent);}else{assert(false);}break;}else{assert(false);}}}return true;
}

三.旋转 

        旋转有4种方式:向右旋转,向左旋转,左右双旋,右左双旋这四种

3.1右旋

        看下面的抽象图

 当n=0时全图为

当n=1时全图为

当n=2时我们有3种,但是在a的位置能放第3种,因为别的会自动进行旋转,b和c这三种都可以

  当n=3时就会更多,所以这是列举不完的,针对右旋我们以下面这张图为例:

我们经过右旋后转化成下面的样子,针对的主要就是这几个节点

 

在旋转的过程中需要注意的是,parent节点是不是根节点,注意调整后subL节点的的父节点的调整,还有一点就是subLR是否为空节点,调整后需要将subL节点和parent节点的bf值改为0,我们看下面的代码:

	void RatoteR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;subL->_right = parent;parent->_left = subLR;Node* ppNode = parent->_parent;subL->_parent = parent->_parent;parent->_parent = subL;if (subLR)subLR->_parent = parent;if (parent == _root){_root = subL;}else{if (ppNode->_left == parent)ppNode->_left = subL;elseppNode->_right = subL;}subL->_bf = parent->_bf = 0;}

3.2左旋

        左旋的代码和右旋的类似,不过需要调节的平衡因子为2和1,我们看下面的图片

我们直接上代码:

void RatoteL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;Node* ppNode = parent->_parent;parent->_parent = subR;subR->_left = parent;subR->_parent = ppNode;if (parent == _root){_root = subR;}else{if (ppNode->_left == parent)ppNode->_left = subR;elseppNode->_right = subR;}subR->_bf = parent->_bf = 0;
}
void RatoteRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RatoteR(subR);RatoteL(parent);if (bf == 1){parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;}}

3.3左右双旋

        左右双旋的图片可以看为下面的抽象图:

当我们在b位置插入后再旋转,可以得到:

当我们插入到c位置后再经过旋转,可以得到:

 

当只旋转一次就会做一次镜像旋转,我们先让subL节点左旋,然后让parent右旋,然后进行调节平衡因子,我们看代码:

void RatoteLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RatoteL(subL);RatoteR(parent);if (bf == 1){subL->_bf = -1;}else if (bf == -1){parent->_bf = 1;}
}

3.4右左双旋

        这个和左右双旋类似,我们直接看代码:

	void RatoteRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RatoteR(subR);RatoteL(parent);if (bf == 1){parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;}}

四.测试

        我们直接上代码:

public:	void InOrder(){_InOrder(_root);}bool IsBalance(){return _IsBalance(_root);}
private:void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << "->" << root->_kv.second << endl;int left = _height(root->_left);int right = _height(root->_right);int sub = abs(left - right);cout << "bf-> " << sub<<endl;if (sub >= 2) cout<<"key-> "<< root->_kv.first << endl;_InOrder(root->_right);}int _height(Node* root){if (root == nullptr)return 0;int x = 1 + _height(root->_left);int y = 1 + _height(root->_right);return max(x , y);}bool _IsBalance(Node* root){		if (root == nullptr) return true;int left = _height(root->_left);int right = _height(root->_right);if (abs(right - left) >= 2){return false;}return _IsBalance(root->_left) && _IsBalance(root->_right);}

测试代码:

int main()
{srand(0);AVLTree<int, int> a;vector<int> v;for (int i = 0; i < 1000000; i++){int num = rand() + i;v.push_back(num);}cout << a.IsBalance() << endl;return 0;
}

运行可以看到:

相关文章:

C++进阶之AVL树

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 C进阶​ ​​​​算法 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂 目录 一.前言 二.插入 三.旋转 3.1右旋 …...

sizeof 和 strlen 比较

sizeof 和 strlen 在 C 语言中都是用于获取某种“大小”的&#xff0c;但它们之间有着显著的区别。 sizeof sizeof 是一个运算符&#xff0c;用于计算数据类型或对象在内存中的大小&#xff08;以字节为单位&#xff09;。它可以在编译时确定结果&#xff0c;因为它计算的是类…...

音视频开发—FFmpeg 打开摄像头进行RTMP推流

实验平台&#xff1a;Ubuntu20.04 摄像头&#xff1a;普通USB摄像头&#xff0c;输出格式为YUV422 1.配置RTMP服务器推流平台 使用Nginx 配置1935端口即可&#xff0c;贴上教程地址 ubuntu20.04搭建Nginxrtmp服务器) 2.配置FFmpeg开发环境 过程较为简单&#xff0c;这里不…...

D触发器(D Flip-Flop)与D锁存器(D Latch)

1 基础概念 我们先来简单回顾一下D触发器&#xff08;D flip-flop&#xff09;和D锁存器&#xff08;D latch&#xff09;的概念&#xff0c;以及它们在数字电路中的作用。 1.1 D触发器&#xff08;D Flip-Flop&#xff09; D触发器是一种数字存储器件&#xff0c;它在时钟信号…...

JDK19特性

JDK19特性 一、JAVA19概述 JDK 19 2022 年 9 月 20 日正式发布以供生产使用,非长期支持版本。不过,JDK 19 中有一些比较重要的新特性值得关注。 JDK 19 只有 7 个新特性: JEP 405: Record Patterns(记录模式)[1] (预览)JEP 422: Linux/RISC-V Port[2]JEP 424: Foreign …...

sql语句中常用的函数有那些

1、字符串函数 CONCAT(string1, string2, ...): 连接两个或多个字符串。 UPPER(string): 将字符串转换为大写。 LOWER(string): 将字符串转换为小写。 TRIM(string): 去除字符串两端的空格。 LENGTH(string): 返回字符串的长度。 SUBSTRING(string, start, length): 从字符串中…...

odoo17 小变更3 Warning、 “attrs “和 “states “不再用

odoo17 小变更 1、Warning from odoo.exceptions import ValidationError,Warning ImportError: cannot import name Warning from odoo.exceptions (D:\od172406\odoo\exceptions.py) 2、自 17.0 版起&#xff0c;不再使用 "attrs "和 "states "属性。 …...

Unity3d 游戏暂停(timeScale=0)引起的deltaTime关联的系列问题解决

问题描述 游戏暂停的功能是通过设置timeScale0实现的&#xff0c;不过在暂停游戏的时候&#xff0c;需要对角色进行预览和设置&#xff0c;为了实现这个功能&#xff0c;是通过鼠标控制相机的操作&#xff0c;为了使相机的操作丝滑&#xff0c;获取鼠标操作系数乘以Time.delta…...

服务端代码编写中MySql大小写在Java中报错问题解决

报错信息&#xff1a; 原因&#xff1a;MySql和Java变量大小写产生的冲突。 经过查阅各个博客等&#xff0c;得出浅显结论&#xff08;不一定对&#xff09;&#xff1a;MySql大小写不敏感&#xff0c;Java大小写敏感&#xff0c;当Javabean转为MySql数据库表时&#xff0c;Ja…...

CRMEB 多店商品详情页装修说明

一、功能介绍 商家可调整商品详情各板块样式&#xff0c;可根据不同的需求开启或关闭单独的板块 二、操作流程 装修 > 商品详情 三、功能说明 1、商品信息 可控制商品详情页面商品信息的显示与隐藏 2、会员信息&#xff0c;排行榜 控制商品详情页面会员信息及排行榜的…...

Redis-使用 jedis 操作数据

文章目录 1、Jedis简介2、环境准备3、创建maven普通项目,导入如下依赖4、测试JAVA程序和Redis之间的通信 1、Jedis简介 "Jedis" 通常是作为 "Java Redis" 的缩写或简称来理解的。Java Embedded Data Structures Interface 表示 Java嵌入式数据结构接口 2、…...

简说PIP换源

概述 PIP&#xff08;Python Package Installer&#xff09;是 Python 的包管理工具&#xff0c;用于安装和管理 Python 包。默认情况下&#xff0c;PIP 从 Python 官方的包仓库&#xff08;即 PyPI&#xff09;下载和安装包。然而&#xff0c;由于网络原因&#xff0c;访问官…...

django学习入门系列之第三点《CSS基础样式介绍2》

文章目录 文字对齐方式外边距内边距往期回顾 文字对齐方式 水平对齐方式 text-align: center;垂直对齐方式 /* 注意&#xff0c;这个只能是一行来居中 */ line-height:/*长度*/ ;样例 <!DOCTYPE html> <html lang"en"> <head><meta charset…...

分布式光纤测温DTS在工程现场中稳定性与可靠性如何?

20年前&#xff0c;分布式光纤测温(Distributed Temperature Sensing&#xff0c;DTS)技术的发展尚不成熟&#xff0c;设备成本高昂&#xff0c;其稳定性与可靠性也存在一定问题。然而&#xff0c;经过二十多年的不断发展与创新&#xff0c;DTS技术在工程现场应用中取得了显著进…...

PHP多线程模块parallel的编译安装和多线程编程演示

从PHP7开始&#xff0c;多线程编原有的pthreads已经不在维护&#xff0c;而是使用parallel替代。 由于是新的模块&#xff0c;样例代码很少&#xff0c;这里总结一个简单的代码和详细的备注供大家参考。 编译和安装 parallel需要启用ZTS&#xff08;Zend Thread Safety&…...

记录grid布局属性

grid布局 分为容器和项目元素 容器属性 #container{display:grid;grid-template-columns:100px 100px 100px;/* 1fr 表示比例为占1份 */grid-template-columns:1fr 100px 1fr;/*100px为1列,自动填充,容器宽度不足则换行*/grid-template-columns:repeat(auto-fill,100px);/* …...

12.爬虫---PyMysql安装与使用

12.PyMysql安装与使用 1.安装 PyMySQL2.使用PyMySQL2.1创建数据表2.2连接数据库2.3增加数据2.4修改数据2.5查询数据2.6删除数据2.7关闭连接 3.总结 MySQL 安装可以看这篇文章MySql 安装与使用&#xff08;非常详细&#xff09; 1.安装 PyMySQL PyMySQL是Python中用于连接MySQL…...

VS2022遇到的两个问题

问题一&#xff1a;找不到定义的头文件 别的博主说是&#xff1a;在属性页里面进行改写&#xff0c;改成是&#xff0c;我试过之后并不行&#xff1b; 解决思路&#xff1a;但其实在右边视图里面找到你自己定义的头文件加到你运行文件中就行&#xff1b;因为程序就只有一个入口…...

【Android14 ShellTransitions】(六)SyncGroup完成

这一节的内容在WMCore中&#xff0c;回想我们的场景&#xff0c;是在Launcher启动某一个App&#xff0c;那么参与动画的就是该App对应Task&#xff08;OPEN&#xff09;&#xff0c;以及Launcher App对应的Task&#xff08;TO_BACK&#xff09;。在确定了动画的参与者后&#x…...

技术管理转型之战:决策之道-管理中的智慧与策略

文章目录 引言一、决策的重要性二、常见的决策方式1. 理性决策&#xff08;Rational Decision Making&#xff09;2. 有限理性&#xff08;Bounded Rationality&#xff09;3. 直觉决策&#xff08;Intuitive Decision Making&#xff09;4. 循证管理&#xff08;Evidence-Base…...

Shell脚本:条件语句(if、case)

目录 硬编码 硬编码的缺点 条件判断 $? 命令行语句 判断指定目录是否存在 判断指定文件是否存在 判断指定对象是否存在 表达式形式语句 判断对象是否存在 判断对象是否有权限 与、或、非 运算 与运算 或运算 非运算 比较大小 判断磁盘利用率实验步骤 字符串…...

在Linux上为Windows目标配置Qt交叉编译

问题描述 我想使用Linux x86_64主机为Windows x86_64目标交叉编译Qt库&#xff08;最终也包括我的应用程序&#xff09;。我觉得自己已经接近成功了&#xff0c;但可能对整个过程有一些基本的误解。 我从在我的Fedora机器上安装所有mingw包开始&#xff0c;并修改了win32-g的…...

Introduction to linear optimization 第 2 章课后题答案 11-15

线性规划导论 Introduction to linear optimization (Dimitris Bertsimas and John N. Tsitsiklis, Athena Scientific, 1997)&#xff0c; 这本书的课后题答案我整理成了一个 Jupyter book&#xff0c;发布在网址&#xff1a; https://robinchen121.github.io/manual-introdu…...

Java——包

一、包 1、简要介绍 在Java编程语言中&#xff0c;包&#xff08;Package&#xff09; 是一种用来组织和管理类&#xff08;Class&#xff09;和接口&#xff08;Interface&#xff09;的机制。包为开发者提供了一种逻辑分组的方式&#xff0c;使代码更加模块化、结构化和易于…...

Pipeline知识小记

在scikit-learn&#xff08;通常缩写为sklearn&#xff09;中&#xff0c;Pipeline是一个非常重要的工具&#xff0c;它允许你将多个数据转换步骤&#xff08;如特征选择、缩放等&#xff09;和估计器&#xff08;如分类器、回归器等&#xff09;组合成一个单一的估计器对象。这…...

postman国内外竞争者及使用详解分析

一、postman简介 Postman 是一款广泛使用的 API 开发和测试工具&#xff0c;适用于开发人员和测试人员。它提供了一个直观的界面&#xff0c;用于发送 HTTP 请求、查看响应、创建和管理 API 测试用例&#xff0c;以及自动化 API 测试工作流程。以下是 Postman 的主要功能和特点…...

人工智能对决:ChatGLM与ChatGPT,探索发展历程

图: a robot is writing code on a horse, By 禅与计算机程序设计艺术 目录 ChatGLM:...

探索Python元类的奥秘及其应用场景

探索Python元类的奥秘及其应用场景 一、引言 在Python中&#xff0c;元类&#xff08;Metaclasses&#xff09;是一个相对高级且容易被忽视的主题。然而&#xff0c;对于深入理解Python的面向对象编程模型以及进行高级框架和库的设计来说&#xff0c;元类是一个不可或缺的工具…...

C语言基础关键字的含义和使用方法

​关键字在C语言中扮演着非常重要的角色&#xff0c;它们定义了语言的基本构造和语法规则&#xff0c;通过使用关键字&#xff0c;开发者可以创建变量、定义数据类型、控制程序流程&#xff08;如循环和条件判断&#xff09;、声明函数等。由于这些字是保留的&#xff0c;所以编…...

【Golang - 90天从新手到大师】Day09 - string

系列文章合集 Golang - 90天从新手到大师 String 一个字符串是一个不可改变的字节序列。字符串可以包含任意的数据&#xff0c;但是通常是用来包含人类可读的文本。 len()返回字符串字节数目&#xff08;不是rune数&#xff09;。 通过索引可以访问某个字节值&#xff0c;0…...

单页的网站怎么做/商品标题优化

现在用到最多的Win10系统是Win10专业版&#xff0c;用户重装Win10专业版系统的目的就是为了解决电脑遇到的问题&#xff0c;然而重装系统后还是会出现许许多多的问题&#xff0c;比如说部分软件打不开了&#xff0c;闪退的问题。如果您也遇到了相同的问题&#xff0c;下面就是小…...

网站制作建设有哪些/软文客

写在最前&#xff1a;该篇文章还未完成&#xff0c;待进一步更新...。。一、初始 MycatMHALVS1、为什么选择 Mycat&#xff1f;互联网的高速发展使分布式技术兴起&#xff0c;当系统的压力越来越大时&#xff0c;人们首先想到的解决方案就是想上扩展(scale up)&#xff0c;简单…...

主流科技类的网站都有哪些/抖音关键词推广

最近学习AIR 发现有篇好文章&#xff0c;翻译下&#xff0c;和大家共享。原文地址:[url]http://www.smashingmagazine.com/2009/04/07/adobe-air-developers-toolbox-resources-and-tutorials/[/url]现以生成电子版&#xff0c;下载地址:[url]http://xiayuanfeng.javaeye.com/b…...

东营网站备案代理公司/北京高端网站建设

文章目录rabbitmq 从入门到精通消息队列介绍1.1 介绍1.2 MQ解决什么问题应用解耦流量消峰消息分发异步消息1.3 常见消息队列及比较Rabbitmq安装2.1 服务端原生安装2.2 服务端Docker安装2.3 客户端安装2.4 设置用户和密码基于Queue实现生产者消费者模型基本使用&#xff08;生产…...

网站建设合同法/百度站长工具app

今天来聊一个面试中经常会被问到的问题&#xff0c;咱们一起必须把这个问题搞懂。 问题&#xff1a;spring 中为什么需要用三级缓存来解决这个问题&#xff1f;用二级缓存可以么&#xff1f; 我先给出答案&#xff1a;不可用。 这里先声明下&#xff1a; 本文未指明 bean scope…...

帮别人做时时彩网站/免费建自己的网址

华为防火墙USG5500重点&#xff1a;什么是防火墙&#xff1b;防火墙基础&#xff1b;防火墙功能配置一.什么是防火墙&#xff1a;1.什么是防火墙&#xff1a;防火墙主要用于保护一个网络免受来自另一个网络的***和***行为&#xff0c;因其隔离、防守属性&#xff0c;防火墙灵活…...