【高级程序设计语言C++】AVL树

news2024/11/13 9:10:10

  • 1. AVL树的概念
  • 2. AVL树的旋转
    • 2.1. 左单旋
    • 2.2 右单旋
    • 2.3 左右双旋
    • 2.4 右左双旋

1. AVL树的概念

AVL树是一种自平衡二叉搜索树,它在每次插入或删除节点时自动调整以保持树的平衡。AVL树的平衡是通过节点的高度差来衡量的,即左子树的高度和右子树的高度之差不超过1。

AVL树的特点如下:

  • 每个节点都有一个平衡因子,定义为左子树的高度减去右子树的高度。平衡因子的值只能是-1、0或1。
  • AVL树中的任何节点的左子树和右子树都是AVL树。
  • 对于AVL树中的每个节点,左子树的高度和右子树的高度之差不超过1。

当向AVL树中插入新节点或删除节点时,AVL树会根据节点的平衡因子进行自动调整。如果插入或删除导致某个节点的平衡因子超过了允许的范围(-1、0或1),则需要通过旋转操作来重新平衡树。

2. AVL树的旋转

AVL树的旋转操作包括左旋和右旋。左旋是指将一个节点的右子树提升为其父节点,并将父节点降为其左子节点。右旋是指将一个节点的左子树提升为其父节点,并将父节点降为其右子节点。通过旋转操作,AVL树可以保持平衡。

2.1. 左单旋

左单旋的情况简图如下:

img

需要左单旋,那么就是右边的分支出现了平衡因子异常,他的形象图类似一条直线。

img

总体来说就是右边高,需要向左旋转,依据的是平衡因子来确定是否需要旋转。

当父亲的平衡因子为2,子树的平衡因子为1的时候,就需要左单旋。旋转完成后,需要注意平衡因子的更新。

// 左单旋
void RotateL(Node* pParent)
{
    Node* subR = pParent->_pRight;
    Node* subRL = subR->_pLeft;

    pParent->_pRight = subRL;
    if (subRL)
    {
        subRL->_pParent = pParent;
    }

    Node* pPParent = pParent->_pParent;
    subR->_pLeft = pParent;
    pParent->_pParent = subR;
    if (pPParent)
    {
        if (pParent == pPParent->_pLeft)
        {
            pPParent->_pLeft = subR;
        }
        else if (pParent == pPParent->_pRight)
        {
            pPParent->_pRight = subR;
        }
        subR->_pParent = pPParent;
    }
    else
    {
        _root = subR;
        _root->_pParent = nullptr;
    }
    subR->_bf = pParent->_bf = 0;
}

旋转之后的树状图如下:

img

2.2 右单旋

img

具体的图像请读者自行画出。

总体来说就是,左边高,就需要往右边旋转,依据平衡因子来决定。

当父亲的平衡因子为-2,子树的平衡因子为-1时就需要右单旋。旋转完成后需要注意平衡因子的更新。

// 右单旋
void RotateR(Node* pParent)
{
    Node* subL = pParent->_pLeft;
    Node* subLR = subL->_pRight;
    pParent->_pLeft = subLR;
    if (subLR)
    {
        subLR->_pParent = pParent;
    }
    Node* pPParent = pParent->_pParent;
    subL->_pRight = pParent;
    pParent->_pParent = subL;
    if (pPParent)
    {
        if (pPParent->_pLeft == pParent)
        {
            pPParent->_pLeft = subL;
        }
        else if (pPParent->_pRight == pParent)
        {
            pPParent->_pRight = subL;
        }
        subL->_pParent = pPParent;
    }
    else
    {
        _root = subL;
        _root->_pParent = nullptr;
    }
    pParent->_bf = subL->_bf = 0;
}

2.3 左右双旋

img

具体来说就是,先进行左单旋,捋直后进行右单旋。依据平衡因子来决定。

当父亲的平衡因子为-2,子树的平衡因子为1时,就要进行左右双旋。

void RotateLR(Node* pParent)
	{
		Node* subL = pParent->_pLeft;
		Node* subLR = subL->_pRight;
		int bf = subLR->_bf;
		RotateL(subL);
		RotateR(pParent);
		if (bf == 0)
		{
			subL->_bf = 0;
			pParent->_bf = 0;
			subLR->_bf = 0;
		}
		else if (bf == -1)
		{
			subL->_bf = 0;
			pParent->_bf = 1;
			subLR->_bf = 0;
		}
		else if (bf == 1)
		{
			subL->_bf = -1;
			pParent->_bf = 0;
			subLR->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}

2.4 右左双旋

img

参考左右双旋,根据上图自行绘出节点的走势。

右左双旋的依据也是根据平衡因子来决定的,当父亲的平衡因子为2,子树的平衡因子为-1时,即要进行右左双旋。

// 右左双旋
void RotateRL(Node* pParent)
{
    Node* subR = pParent->_pRight;
    Node* subRL = subR->_pLeft;
    int bf = subRL->_bf;
    RotateR(subR);
    RotateL(pParent);
    if (bf == -1)
    {
        subRL->_bf = 0;
        pParent->_bf = 1;
        subR->_bf = 0;
    }
    else if (bf == 0)
    {
        subRL->_bf = 0;
        pParent->_bf = 0;
        subR->_bf = 0;
    }
    else if (bf == 1)
    {
        subRL->_bf = 0;
        pParent->_bf = -1;
        subR->_bf = 0;
    }
    else
    {
        assert(false);
    }
}

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

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

相关文章

Gartner:2022年全球IaaS公有云服务市场增长30%,首次突破1000亿美元

根据Gartner的统计结果,2022年全球基础设施即服务(IaaS)市场从2021年的928亿美元增长到1203亿美元,同比增长29.7%。亚马逊在2022年继续排在IaaS市场的第一名,其次是微软、阿里巴巴、谷歌和华为。 最新消息,…

Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台免费搭建 qt

Java版知识付费源码 Spring CloudSpring BootMybatisuniapp前后端分离实现知识付费平台 提供职业教育、企业培训、知识付费系统搭建服务。系统功能包含:录播课、直播课、题库、营销、公司组织架构、员工入职培训等。 提供私有化部署,免费售…

无涯教程-Lua - 文件I/O

I/O库用于在Lua中读取和处理文件。 Lua中有两种文件操作,即隐式(Implicit)和显式(Explicit)操作。 对于以下示例,无涯教程将使用例文件test.lua,如下所示。 -- sample test.lua -- sample2 test.lua 一个简单的文件打开操作使用以下语句。…

计算机毕设 深度学习猫狗分类 - python opencv cnn

文章目录 0 前言1 课题背景2 使用CNN进行猫狗分类3 数据集处理4 神经网络的编写5 Tensorflow计算图的构建6 模型的训练和测试7 预测效果8 最后 0 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往…

vscode 第一个文件夹在上一层文件夹同行,怎么处理

我的是这样的 打开终端特别麻烦 解决方法就是 打开vscode里边的首选项 进入设置 把Compact Folders下边对勾给勾掉

acwing 1064 小国王 线性状态压缩DP

输入 3 2输出 16&#x1f37a; AC code #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<vector>using namespace std;typedef long long ll; const int N 12; const int M 1 << 10, K 110;//…

Openlayers:DWS-DD坐标形式互相转换

参考google地图, 坐标分为DD和DMS两种形式。 在本示例中,DWS-DD做互相转换。Openlayers处理DD-》DMS很简单,逆向操作需要做反向推导,方法参考源代码。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhuanlan),还是大剑师兰特(CSDN) * @此源代码版权归大剑师兰特所有…

Linux【网络基础】IP协议

文章目录 一、IP协议&#xff08;1&#xff09;IP地址协议概念和理解&#xff08;2&#xff09;IP地址协议格式&#xff08;3&#xff09;网络号和主机号&#xff08;4&#xff09;地址管理&#xff08;一&#xff09;分配IP地址方法&#xff08;二&#xff09;CIDR分配IP地址&…

基本频谱分析

基本频谱分析 傅里叶变换是用于对时域信号执行频率和功率谱分析的工具。 频谱分析数量 频谱分析研究非均匀采样的离散数据中包含的频谱。傅里叶变换是通过在频率空间表示基于时间或空间的信号来揭示该信号的频率分量的工具。下表列出了用于描述和解释信号属性的常用量。要了…

Axios GET 请求:从入门到实践

在进行网络请求时&#xff0c;axios 是一个非常常用的请求库。本文将介绍如何使用 axios 发起 GET 请求&#xff0c;并详细列出传参的几种写法。同时会提供一个实践案例&#xff0c;其中包含基本路由与请求处理的过程&#xff0c;并确保在 IDE 编辑器中可以顺利运行。 什么是 a…

STM32入门——GPIO输入输出

GPIO简介 GPIO&#xff08;General Purpose Input Output&#xff09;通用输入输出口 可配置为8种输入输出模式引脚电平&#xff1a;0V~3.3V&#xff0c;部分引脚可容忍5V输出模式下可控制端口输出高低电平&#xff0c;用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等输入模…

ES6 数组的用法

1. forEach() 用来循环遍历的 for 数组名.forEach(function (item,index,arr) {})item:数组每一项 , index : 数组索引 , arr:原数组作用: 用来遍历数组 let arr [1, 2, 3, 4]; console.log(arr); let arr1 arr.forEach((item, index, arr) > {console.log(item, index…

SpringBoot第29讲:SpringBoot集成MySQL - MyBatis-Plus代码自动生成

SpringBoot第29讲&#xff1a;SpringBoot集成MySQL - MyBatis-Plus代码自动生成 本文是SpringBoot第29讲&#xff0c;主要介绍 MyBatis-Plus代码自动生成&#xff0c;以及产生此类代码生成工具的背景和此类工具的基本实现原理。 文章目录 SpringBoot第29讲&#xff1a;SpringBo…

em3288 linux_4.19 第一次烧写无法进入内核的情况

1. 情况一&#xff1a; /DDR Version 1.11 20210818 In SRX Channel a: DDR3 400MHz Bus Width32 Col10 Bank8 Row15 CS1 Die Bus-Width16 Size1024MB Channel b: DDR3 400MHz Bus Width32 Col10 Bank8 Row15 CS1 Die Bus-Width16 Size1024MB OUT Boot1 Release Time: Jul 22 2…

pyecharts包的简单使用

pyecharts简介 Pyecharts是一个Python的数据可视化库。 它基于ECharts&#xff0c;一个由百度开发的流行的JavaScript图表库。Pyecharts旨在为Python用户提供一种简便的方法来创建各种类型的交互式图表&#xff0c;包括折线图、柱状图、散点图、饼图、地图等。通过使用Pyechar…

场景库之高精度地图编辑器

一、背景介绍 高精度地图编辑器是场景库生产所需的必要工具&#xff0c;地图编辑器基于JS开发&#xff0c;可对指定的地图进行描绘&#xff0c;生成数字高精度地图。 二、功能介绍 路网元素支持&#xff1a; 类别元素图片交叉口交叉口安全岛交通岛导流岛道路中心圈路口边缘线…

ATTCK实战系列-红队评估 (红日靶场3)Vulnstack三层网络域渗透靶场

文章目录 环境配置靶场介绍靶场设置 外网渗透信息收集端口扫描目录扫描 漏洞发现与利用获取ssh账号密码&#xff0c;登录centos 提权 内网渗透建立代理内网信息收集smb暴破&#xff0c;获取本地管理员密码 横向移动使用psexec模块上线msf 环境配置 靶场介绍 靶场地址 http:/…

[LeetCode]链表相关题目(c语言实现)

文章目录 LeetCode203. 移除链表元素LeetCode237. 删除链表中的节点LeetCode206. 反转链表ⅠLeetCode92. 反转链表 II思路 1思路 2 LeetCode876. 链表的中间结点剑指 Offer 22. 链表中倒数第k个节点LeetCode21. 合并两个有序链表LeetCode86. 分隔链表LeetCode234. 回文链表Leet…