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

盐城企业做网站/南昌seo代理商

盐城企业做网站,南昌seo代理商,怎么快速建一个网站,网站推荐靠谱的能长久看的目录 一、AVL树的概念 二、AVL树的实现 1.AVL树节点的定义 2.AVL树的插入 3.AVL树的旋转 4.AVL树的验证 三、AVL树的性能 四、完结撒❀ 一、AVL树的概念 二叉搜索树虽可以缩短查找的效率,但 如果数据有序或接近有序二叉搜索树将退化为单支树,查 …

目录

一、AVL树的概念

二、AVL树的实现

1.AVL树节点的定义

2.AVL树的插入

3.AVL树的旋转

4.AVL树的验证

三、AVL树的性能

四、完结撒❀


一、AVL树的概念

二叉搜索树虽可以缩短查找的效率,但 如果数据有序或接近有序二叉搜索树将退化为单支树,查
找元素相当于在顺序表中搜索元素,效率低下 。因此,两位俄罗斯的数学家 G.M.Adelson-Velskii
E.M.Landis 1962 发明了一种解决上述问题的方法: 当向二叉搜索树中插入新结点后,如果能保证每个结点的左右 子树高度之差的绝对值不超过 1( 需要对树中的结点进行调整 ) ,即可降低树的高度,从而减少平均 搜索长度。
一棵 AVL 树或者是空树,或者是具有以下性质的二叉搜索树:
● 它的左右子树都是 AVL
● 左右子树高度之差 ( 简称平衡因子 ) 的绝对值不超过 1(-1/0/1)

如果一棵二叉搜索树是高度平衡的,它就是 AVL 树。如果它有 n 个结点,其高度可保持在
O(log2 n) ,搜索时间复杂度 O(log2 n)

二、AVL树的实现

1.AVL树节点的定义

AVL树节点的定义:

template<class T>
struct AVLTreeNode
{AVLTreeNode(const T& data): _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr), _data(data), _bf(0){}AVLTreeNode<T>* _pLeft;   // 该节点的左孩子AVLTreeNode<T>* _pRight;  // 该节点的右孩子AVLTreeNode<T>* _pParent; // 该节点的双亲T _data;int _bf;                  // 该节点的平衡因子
};

2.AVL树的插入

AVL 树就是在二叉搜索树的基础上引入了平衡因子,因此 AVL 树也可以看成是二叉搜索树。那么
AVL 树的插入过程可以分为两步:
1. 按照二叉搜索树的方式插入新节点
2. 调整节点的平衡因子
bool Insert(const pair<K, V>& kv)
{// 1. 先按照二叉搜索树的规则将节点插入到AVL树中if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else{//插入相同值return false;}}//找到cur所在位置cur = new Node(kv);if (parent->_kv.first > cur->_kv.first){parent->_left = cur;cur->_parent = parent;}else{parent->_right = cur;cur->_parent = parent;}// 2. 新节点插入后,AVL树的平衡性可能会遭到破坏,此时就需要更新平衡因子,并检测是否//破坏了AVL树的平衡性/*pCur插入后,pParent的平衡因子一定需要调整,在插入之前,pParent的平衡因子分为三种情况:-1,0, 1, 分以下两种情况:1. 如果pCur插入到pParent的左侧,只需给pParent的平衡因子-1即可2. 如果pCur插入到pParent的右侧,只需给pParent的平衡因子+1即可此时:pParent的平衡因子可能有三种情况:0,正负1, 正负21. 如果pParent的平衡因子为0,说明插入之前pParent的平衡因子为正负1,插入后被调整成0,此时满足
AVL树的性质,插入成功2. 如果pParent的平衡因子为正负1,说明插入前pParent的平衡因子一定为0,插入后被更新成正负1,此
时以pParent为根的树的高度增加,需要继续向上更新3. 如果pParent的平衡因子为正负2,则pParent的平衡因子违反平衡树的性质,需要对其进行旋转处理*///更新平衡因子while (parent){if (parent->_left == cur){parent->_bf--;}else{parent->_bf++;}if (parent->_bf == 0){//二叉树高度没问题,更新结束break;}else if (parent->_bf == 1 || parent->_bf == -1){// 插入前双亲的平衡因子是0,插入后双亲的平衡因子为1 或者 -1 ,说明以双亲为根的二叉树// 的高度增加了一层,因此需要继续向上调整cur = parent;parent = parent->_parent;}else if (parent->_bf == -2 || parent->_bf == 2){//双亲的平衡因子为正负2,违反了AVL树的平衡性//二叉树平衡被破坏,需要旋转完成平衡//判断是右单旋还是左单旋还是双旋//右单旋if (parent->_bf == -2 && cur->_bf == -1){//...}//左单旋else if (parent->_bf == 2 && cur->_bf == 1){//...}//左右双旋else if (parent->_bf == -2 && cur->_bf == 1){//...}//右左双旋else if (parent->_bf == 2 && cur->_bf == -1){//...}}else{//理论上不会出现这种状况assert(false);}}return true;
}

3.AVL树的旋转

如果在一棵原本是平衡的 AVL 树中插入一个新节点,可能造成不平衡,此时必须调整树的结构,
使之平衡化。根据节点插入位置的不同, AVL 树的旋转分为四种:
1) 新节点插入较高左子树的左侧---左左:右单旋

/*上图在插入前,AVL树是平衡的,新节点插入到30的左子树(注意:此处不是左孩子)中,30左
子树增加了一层,导致以60为根的二叉树不平衡,要让60平衡,只能将60左子树的高度减少一层,右子
树增加一层,即将左子树往上提,这样60转下来,因为60比30大,只能将其放在30的右子树,而如果30有
右子树,右子树根的值一定大于30,小于60,只能将其放在60的左子树,旋转完成后,更新节点
的平衡因子即可。在旋转过程中,有以下几种情况需要考虑:1. 30节点的右孩子可能存在,也可能不存在2. 60可能是根节点,也可能是子树如果是根节点,旋转完成后,要更新根节点如果是子树,可能是某个节点的左子树,也可能是右子树此处可举一些详细的例子进行画图,考虑各种情况,加深旋转的理解
*/
void _RotateR(Node Parent)
{// SubL: Parent的左孩子// SubLR: Parent左孩子的右孩子,注意:该Node SubL = Parent->_Left;Node SubLR = SubL->_Right;// 旋转完成之后,30的右孩子作为双亲的左孩子Parent->_Left = SubLR;// 如果30的左孩子的右孩子存在,更新亲双亲if (SubLR)SubLR->_Parent = Parent;// 60 作为 30的右孩子SubL->_Right = Parent;// 因为60可能是棵子树,因此在更新其双亲前必须先保存60的双亲Node Parent = Parent->_Parent;// 更新60的双亲Parent->_Parent = SubL;// 更新30的双亲SubL->_Parent = Parent;// 如果60是根节点,根新指向根节点的指针if (NULL == Parent){_root = SubL;SubL->_Parent = NULL;}else{// 如果60是子树,可能是其双亲的左子树,也可能是右子树if (Parent->_Left == Parent)Parent->_Left = SubL;elseParent->_Right = SubL;}// 根据调整后的结构更新部分节点的平衡因子Parent->_bf = SubL->_bf = 0;
}

2) 新节点插入较高右子树的右侧---右右:左单旋

//左单旋
void LNode(Node* parent)
{/*if (parent == _root){Node* pparent = nullptr;}else{Node* pparent = parent->_parent;}*/Node* pparent = parent->_parent;Node* subR = parent->_right;Node* subRL = subR->_left;parent->_left = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;parent->_parent = subR;if (pparent){subR->_parent = pparent;if (pparent->_left = parent){pparent->_left = subR;}else{pparent->_right = subR;}}else{_root = subR;subR->_parent = nullptr;}parent->_bf = subR->_bf = 0;
}

3) 新节点插入较高左子树的右侧---左右:先左单旋再右单旋

将双旋变成单旋后再旋转,即: 先对 30 进行左单旋,然后再对 90 进行右单旋 ,旋转完成后再
考虑平衡因子的更新。
// 旋转之前,60的平衡因子可能是-1/0/1,旋转完成之后,根据情况对其他节点的平衡因子进
//行调整
void _RotateLR(Node Parent)
{Node SubL = Parent->_Left;Node SubLR = SubL->_Right;// 旋转之前,保存pSubLR的平衡因子,旋转完成之后,需要根据该平衡因子来调整其他节点的平衡因子int bf = SubLR->_bf;// 先对30进行左单旋_RotateL(Parent->_Left);// 再对90进行右单旋_RotateR(Parent);if (1 == bf)SubL->_bf = -1;else if (-1 == bf)Parent->_bf = 1;
}

4) 新节点插入较高右子树的左侧---右左:先右单旋再左单旋

//右左双旋
void RLNode(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RNode(parent->_right);LNode(parent);if (bf == 1){subRL->_bf = 0;subR->_bf = 0;parent->_bf = -1;}else if (bf == -1){subRL->_bf = 0;subR->_bf = 1;parent->_bf = 0;}else if (bf == 0){subRL->_bf = 0;subR->_bf = 0;parent->_bf = 0;}else{//理论没有该状况assert(false);}
}
总结:
假如以 Parent 为根的子树不平衡,即 Parent 的平衡因子为 2 或者 -2 ,分以下情况考虑
1)Parent 的平衡因子为 2 ,说明 Parent 的右子树高,设 Parent 的右子树的根为 SubR
SubR 的平衡因子为 1 时,执行左单旋
SubR 的平衡因子为 -1 时,执行右左双旋
2)Parent 的平衡因子为 -2 ,说明 Parent 的左子树高,设 Parent 的左子树的根为 SubL
SubL 的平衡因子为 -1 是,执行右单旋
SubL 的平衡因子为 1 时,执行左右双旋
旋转完成后,原 Parent 为根的子树个高度降低,已经平衡,不需要再向上更新。

4.AVL树的验证

AVL 树是在二叉搜索树的基础上加入了平衡性的限制,因此要验证 AVL 树,可以分两步:
        1. 验证其为二叉搜索树
            如果中序遍历可得到一个有序的序列,就说明为二叉搜索树
        2. 验证其为平衡树
            ● 每个节点子树高度差的绝对值不超过1(注意节点中如果没有平衡因子 )
            ● 节点的平衡因子是否计算正确
int _size(Node* root)
{return root == nullptr ? 0 : _size(root->_left) + _size(root->_right) + 1;
}int _Height(Node* root)
{if (root == nullptr){return 0;}return max(_Height(root->_left), _Height(root->_right)) + 1;
}bool _IsBalance(Node* root)
{if (root == nullptr){return true;}int LeftHeight = _Height(root->_left);int RightHeight = _Height(root->_right);if (abs(LeftHeight - RightHeight) >= 2){return false;}//可以顺便再检查一下平衡因子if (abs(LeftHeight - RightHeight) != root->_bf){cout << root->_kv.first << endl;return false;}return _IsBalance(root->_left) && _IsBalance(root->_right);
}

三、AVL树的性能

AVL 树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过 1 ,这
样可以保证查询时高效的时间复杂度,即 log2 N 。但是如果要对 AVL 树做一些结构修改的操 作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时, 有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数 据的个数为静态的 ( 即不会改变 ) ,可以考虑 AVL 树,但一个结构经常修改,就不太适合。

四、完结撒❀

如果以上内容对你有帮助不妨点赞支持一下,以后还会分享更多编程知识,我们一起进步。
最后我想讲的是,据说点赞的都能找到漂亮女朋友❤

相关文章:

C++ AVL树 详细讲解

目录 一、AVL树的概念 二、AVL树的实现 1.AVL树节点的定义 2.AVL树的插入 3.AVL树的旋转 4.AVL树的验证 三、AVL树的性能 四、完结撒❀ 一、AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但 如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查 …...

Faster R-CNN:端到端的目标检测网络

本文回顾了由微软研究人员开发的 Faster R-CNN 模型。Faster R-CNN 是一种用于物体检测的深度卷积网络&#xff0c;在用户看来&#xff0c;它是一个单一的、端到端的统一网络。该网络可以准确快速地预测不同物体的位置。为了真正理解 Faster R-CNN&#xff0c;我们还必须快速概…...

如何给 MySQL 表和列授予权限?(官方版)

目录 授予表级别权限 授予列级别权限 如何给MySQL表和列授予权限是MySQL数据操作中非常重要的步骤&#xff0c;也是企业级使用MySQL数据库的起步点&#xff0c;以下分别参照官方教程整理的MySQL数据库的权限操作。 以下的语句可以直接使用MySQL的命令行进行操作&#xff08;如何…...

攻防世界testre做法(考点:base58)

在做这道题目之前&#xff0c;我们先来简单了解一下base64加密和base58加密&#xff0c;先来说一些预备知识&#xff0c;bit为1个位&#xff0c;即一个0或1&#xff0c;八个位组成一个字节&#xff0c;即八个二进制数。 base64编码原理&#xff1a;1&#xff0c;在使用base64加…...

计算机视觉与模式识别实验1-1 图像的直方图平衡

文章目录 &#x1f9e1;&#x1f9e1;实验流程&#x1f9e1;&#x1f9e1;1.读入图像‘rice.png’&#xff0c;在一个窗口中显示灰度级n64&#xff0c;128和256的图像直方图。2.调解图像灰度范围&#xff0c;观察变换后的图像及其直方图的变化。3.分别对图像‘pout.tif’和‘ti…...

【C++课程学习】:C++入门(函数重载)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f308;函数重载&#xff1a; &#x1f349;1.参数个数不同&#xff1a; &#x1f349;2.参数…...

skywalking介绍及搭建

链路追踪框架比对&#xff1a; skywalking安装部署&#xff1a; 下载地址&#xff1a;Downloads | Apache SkyWalking 配置微服务与skywalking整合&#xff1a; copy agent/optional-plugins/apm-spring-cloud-getway-xx.jar到plugins&#xff0c;然后重启skywalking 监控界面…...

分析示例 | Simufact焊接工艺仿真变形精确预测汽车结构

导语 焊接是汽车制造过程中一个关键环节&#xff0c;白车身、发动机、底盘和变速箱等都离不开焊接工艺的应用&#xff0c;主要涉及气保焊、电阻点焊、激光焊、电子束焊等多种焊接工艺。由于汽车车型众多、成形结构复杂、汽车制造质量、效率、成本等方面的综合要求。如何高效、…...

模式识别选择题

影响K-均值聚类算法效果的主要因素之一是什么&#xff1f; A. 初始聚类中心的选取 B. 样本输入顺序 C. 模式相似性测度 D. 分类准则 答案&#xff1a;A支持向量机&#xff08;SVM&#xff09;在处理非线性问题时&#xff0c;通常使用什么方法&#xff1f; A. 引入核函数 B. 增加…...

【Java基础】线程方法

start()&#xff1a;启动线程&#xff0c;使线程进入就绪状态。 run()&#xff1a;线程执行的代码逻辑&#xff0c;需要重写该方法。 停止线程 void interrupt() 中断线程&#xff0c;让它重新去争抢cpu 如果目标线程长时间等待&#xff0c;则应该使用interrupt方法来中断等待…...

C++之动态数组

C给我们提供了一个叫Vector的类&#xff0c;这个Vector在std命名空间中。这个Vector有点像一个集合&#xff0c;一个不强制其实际元素具有唯一性的集合&#xff0c;和数组一样&#xff0c;但是和C普通的数组又不太一样&#xff0c;和标准的数组不同当你创建Vector时&#xff0c…...

使用 image-combiner 开源项目实现对海报图片的生成

1&#xff1a;gitee 项目地址 image-combiner: ImageCombiner是一个专门用于Java服务端图片合成的工具&#xff0c;没有很复杂的功能&#xff0c;简单实用&#xff0c;从实际业务场景出发&#xff0c;提供简单的接口&#xff0c;几行代码即可实现图片拼合&#xff08;当然用于…...

【缓存】框架层常见问题和对策

缓存是为了加快读写速度&#xff0c;再了解redis这类框架层的缓存应用之前&#xff0c;我们不妨先思考下操作系统层面的缓存解决方案&#xff0c;这样有助于我们更深的理解缓存&#xff0c;哪些是系统层面的&#xff0c;哪些是服务层面。 以下是一些常见的缓存问题及其解决方案…...

【FAS】《CN103106397B》

原文 CN103106397B-基于亮瞳效应的人脸活体检测方法-授权-2013.01.19 华南理工大学 方法 / 点评 核心方法用的是传统的形态学和模板匹配&#xff0c;亮点是双红外发射器做差分 差分&#xff1a;所述FPGA芯片控制两组红外光源&#xff08;一近一远&#xff09;交替亮灭&…...

3D按F3为什么显示不出模型?---模大狮模型网

对于3D建模软件的用户来说&#xff0c;按下F3键通常是用来显示或隐藏模型的功能之一。然而&#xff0c;有时当按下F3键时&#xff0c;却无法正确显示模型&#xff0c;这可能会让用户感到困惑。模大狮将探讨这种情况发生的可能原因以及解决方法&#xff0c;帮助设计师们更好地理…...

C++设计模式——Adapter适配器模式

一&#xff0c;适配器模式简介 适配器模式是一种结构型设计模式&#xff0c;用于将已有接口转换为调用者所期望的另一种接口。 适配器模式让特定的API接口可以适配多种场景。例如&#xff0c;现有一个名为"Reader()"的API接口只能解析txt格式的文件&#xff0c;给这…...

Python文本处理利器:jieba库全解析

文章目录 Python文本处理利器&#xff1a;jieba库全解析第一部分&#xff1a;背景和功能介绍第二部分&#xff1a;库的概述第三部分&#xff1a;安装方法第四部分&#xff1a;常用库函数介绍1. 精确模式分词2. 全模式分词3. 搜索引擎模式分词4. 添加自定义词典5. 关键词提取 第…...

【C/C++】C语言如何实现类似C++的智能指针?

在C中&#xff0c;智能指针是为了自动化资源管理而引入的工具。比如std::unique_ptr和std::shared_ptr等&#xff0c;它们管理着所持有对象的生命周期&#xff0c;可以在智能指针被销毁时自动释放其所持有的资源。在C语言中&#xff0c;虽然没有直接的智能指针概念&#xff0c;…...

九大微服务监控工具详解

Prometheus Prometheus 是一个开源的系统监控、和报警工具包&#xff0c;Prometheus 被设计用来监控“微服务架构”。 主要解决&#xff1a; 监控和告警&#xff1a;Prometheus 可以对系统、和应用程序进行实时监控&#xff0c;并在出现问题时发送告警&#xff1b;数据收集和…...

java aliyun oss上传和下载工具类

java aliyun oss上传和下载工具类 依赖 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.8.0</version></dependency>工具类 import com.alibaba.fastjson.JSON; import c…...

P7 品牌管理

逆向生成页面 新增菜单—商品系统的品牌管理 —product/brand 在代码生成器得到的文件中&#xff0c; main-resources-src-views-modules-product brand.vue、brand-add-or-update.vue放到category.vue同级vue文件有新增、删除按钮&#xff0c;但页面未显示&#xff0c;是因…...

C语言详解(动态内存管理)1

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…...

106.网络游戏逆向分析与漏洞攻防-装备系统数据分析-在UI中显示装备与技能信息

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…...

AWS EMR Serverless

AWS概述 EMR Serverless 简介 在AWS概述一文中简单介绍过AWS EMR, 它是AWS提供的云端大数据平台。借助EMR可以设置集群以便在几分钟内使用大数据框架处理和分析数据。创建集群可参考官方文档&#xff1a;Amazon EMR 入门。但集群创建之后需要一直运行&#xff0c;用户需要管理…...

Java面试题:Redis持久化问题

Redis持久化问题 RDB (Redis Database Backup File) Redis数据快照 将内存中的所有数据都记录到磁盘中做快照 当Redis实例故障重启时,从磁盘读取快照文件恢复数据 使用 save/bgsave命令进行手动快照 save使用主进程执行RDB,对所有命令都进行阻塞 bgsave使用子进程执行R…...

【Java】解决Java报错:ClassCastException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 错误的类型转换2.2 泛型集合中的类型转换2.3 自定义类和接口转换 3. 解决方案3.1 使用 instanceof 检查类型3.2 使用泛型3.3 避免不必要的类型转换 4. 预防措施4.1 使用泛型和注解4.2 编写防御性代码4.3 使用注解和检查工具 5. 示…...

OpenCV-最小外接圆cv::minEnclosingCircle

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 函数原型 void minEnclosingCircle(InputArray points, Point2f& center, float& radius); 参数说明 InputArray类型的…...

大小堆运用巧解数据流的中位数

​​​​​​​​​​ 一、思路 我们将所有数据平分成两份&#xff0c;前面那一部分用小堆来存&#xff0c;后面的部分用大堆来存&#xff0c;这样我们就能立刻拿到中间位置的值。 如果是奇数个数字&#xff0c;那么我们就将把中间值放在前面的大堆里&#xff0c;所以会有两种…...

AI能力边界不断扩展,将对国家安全产生深远影响

文 | 中国信息安全测评中心 王欣 随着 ChatGPT 的发布及相关应用的落地&#xff0c;人工智能技术给全球各个行业带来了一波又一波冲击。GPT-4 多模态大型语言模型更是将人工智能的能力提升到新的高度&#xff0c;无论从技术先进性还是应用实践能力来看&#xff0c;此模型均可被…...

【UnityShader入门精要学习笔记】第十六章 Unity中的渲染优化技术 (上)

本系列为作者学习UnityShader入门精要而作的笔记&#xff0c;内容将包括&#xff1a; 书本中句子照抄 个人批注项目源码一堆新手会犯的错误潜在的太监断更&#xff0c;有始无终 我的GitHub仓库 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 文章目录 移动平台上…...