波奇学C++:AVL树

AVL解决二叉搜索树退化成链表,保证左右子树高度不差过1,尽可能接近满二叉树

AVL树的性质:高度差(平衡因子)的绝对值不超过1(-1/0/1)

平衡因子:右子树高度-左子树高度

用平衡因子控制高度

AVL树节点

class AVLTreeNode
{pair<K, V>_kv; //key/valueAVLTreeNode<K, V>* _left; // 左AVLTreeNode<K, V>* _right;// 右AVLTreeNode<K, V>* _partent;// 父母int _bf;// 平衡因子AVLTreeNode(const pair<K,V>& kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr),_bf(0){}
};

 控制逻辑:增加一个新节点cur

 parent的bf值-1,在右 ,parent的bf加1

如果parent_bf=0,则不再改变,否则继续向上调整,直到parent为0,或者为cur为根节点时。

如果parent的平衡因子为2或者-2,说明树不平衡,要进行旋转调整。

当左边高时(parent=2,cur=1)

柱子a,b,c表示高度为h的AVL树

parent->right=cur->left
cur->left=parent

对于左单旋的理解:1.根节点向左转,2.c树高度增加后a树高2,于是把c的父节点当成根节点使得c的高度方向-1,a的树的方向+1,刚好平衡

同时调整平衡因子数量和parent指针

左单旋

void RotateL(Node* parent){Node* cur = parent->_right; //确定curNode* curleft = parent->_left;parent->_left = curleft;//当h不为0时if (curleft){//调整parent指针curleft->_partent = parent;}cur->_left = parent;//调整新的根节点的parent指针Node* ppnode = parent->_parent;parent->_parent = cur;//根节点特殊情况if (parent == _root){_root = cur;cur->_partent = nullptr;}else{// 确定parent是ppnode的左指针还是右指针if (ppnode->_left==parent){ppnode->_left = cur;}else{ppnode_right = cur;}cur->_partent = ppnode;}parent->_bf = cur->_bf = 0;}

 

 

void RotateR()
{void RotateR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;parent->_left = curright;cur->_right = parent;Node* ppnode = parent->_parent;if (curright){curright->_partent = parent;}parent->_parent = cur;if (ppnode == root){_root = cur;cur->_partent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = cur;}else(ppnode->_right == parent){ppnode->_right = cur;}}cur->_bf = parent->_bf = 0;}
}

 双旋:我们发现左右双旋都是在都是a,c树高度发生变化,具体体现在cur和parent的平衡因子都是相差1,而如果在b树发生变化,无论是左边高还是右边高都会产生双旋问题。具体可以分为四种情况,现在以一种情况为例:

如下图是右边高的b树(现为60-b-c子树)发生改变。

 从图上来讲是90进行右旋,把高的树的树移到外面,再30进行左旋,构建平衡。
 

 

对于父节点为60的树来说,左树成为30节点的右树,右树成为90节点的左树。

所以60的节点的双旋后30,60,90的_bf值不恒为0,30,90节点会受到60的影响。

当60->_bf=1, 30,60,90 =-1 ,0,0

60->_bf=-1, 30,60,90 = 1,0,0

左高右高的区别都是60做根节点,且_bf变化是一样的。

左高:先左旋后右旋,右高,先右旋后左旋。

插入代码和旋转代码

bool Insert(const pair<K, V>& kv){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->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (parent->_kv.first < kv.first){parent->_right = cur;}else if (parent->_kv.first > kv.first){parent->_left = cur;}cur->_parent = parent;return true;// 更新节点while (parent){if (cur == parent->_left){parent->_bf--;}else{parent->_bf++;}if (parent->_bf == 0){break;}else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){if (parent->_bf == 2 && cur->_bf == 1){RotateL(parent);}else if (parent->_bf == -2 && cur->_bf == -1){RotateR(parent);}else if (parent->_bf == 2 && cur->_bf == -1){//右高双旋RotateRL(parent);}else{//左高双旋RotateLR(parent);}}else{assert(false);}}return true; }void RotateL(Node* parent){Node* cur = parent->_right;Node* curleft = parent->_left;parent->_left = curleft;if (curleft){curleft->_parent = parent;}cur->_left = parent;Node* ppnode = parent->_parent;parent->_parent = cur;if (parent == _root){_root = cur;cur->_parent = nullptr;}else{if (ppnode->_left==parent){ppnode->_left = cur;}else{ppnode->_right = cur;}cur->_parent = ppnode;}parent->_bf = cur->_bf = 0;}	void RotateR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;parent->_left = curright;cur->_right = parent;Node* ppnode = parent->_parent;if (curright){curright->_parent = parent;}parent->_parent = cur;if (ppnode == _root){_root = cur;cur->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = cur;}else{ppnode->_right = cur;}}cur->_bf = parent->_bf = 0;}//右高先右后左void RotateRL(Node* parent){Node* cur = parent->_right;Node* curleft = cur->_left;int bf = curleft->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 1){cur->_right->_bf = 0;cur->_left->_bf= -1;}else if (bf == -1){cur->_right->_bf = 0;cur->_left->_bf = 1;}else{;}}void RotateLR(Node* parent){Node* cur = parent->_left;Node* curright = cur->_right;int bf = curright->_bf;RotateL(cur);RotateR(parent);if(bf == 1){cur->_right->_bf = 0;cur->_left->_bf = -1;}else if(bf==-1){cur->_right->_bf = 0;cur->_left->_bf = 1;}else{;}}

检验AVL树

int Height(Node* root){if (root == nullptr)return true;int leftHight = Height(root->_left);int right = Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeigth + 1;}bool IsBalance(Node* root){if (root == nullptr)return true;int leftHight = Height(root->_left);int rightHight = Height(root->_right);if (rightHight-leftHight!=root->_bf){cout<<"平衡因子异常"}return abs(rightHight - leftHight) < 2&& IsBalance(root->_left)&& IsBalance(root->_right);}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【计算机网络】HTTPS协议详解

文章目录 一、HTTPS协议 介绍 1、1 HTTP协议不安全的体现 1、2 什么是 HTTPS协议 二、加密的一些概念 2、1 怎么理解加密 2、2 为什么要加密 2、3 常见的加密方式 2、2、1 对称加密 2、2、2 非对称加密 三、HTTPS协议探究加密过程 3、1 只使用对称加密 3、2 只是用非对称加密 3…

javaee spring整合mybatis

案例一 包含dao层 创建maven webapp项目 maven仓库需要改为阿里云 引入依赖 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-inst…

HarmonyOS/OpenHarmony原生应用-ArkTS万能卡片组件Badge

可以附加在单个组件上用于信息标记的容器组件。该组件从API Version 7开始支持。 支持单个子组件。子组件类型&#xff1a;系统组件和自定义组件&#xff0c;支持渲染控制类型&#xff08;if/else、ForEach和LazyForEach&#xff09;。 一、接口 方法1&#xff1a; Badge(value…

【MySql】Mysql之备份与恢复

目录 一、mysql日志概述 1、日志类型与作用 2、日志配置文件 3、日志配置文件的查询 二、备份的类型❤ 1、物理备份 1.1 冷备份 1.2 热备份 1.3 温备份 2、逻辑备份❤ 2.1 完全备份 2.2 差异备份 2.3 增量备份 2.5 如何选择逻辑备份策略 3、常见的备份方法 3…

ARMv8如何读取cache line中MESI 状态以及Tag信息(tag RAM dirty RAM)并以Cortex-A55示例

Cortex-A55 MESI 状态获取 一&#xff0c;系统寄存器以及读写指令二&#xff0c;Cortex-A55 Data cache的MESI信息获取&#xff08;AARCH 64&#xff09;2.1 将Set/way信息写入Data Cache Tag Read Operation Register2.2 读取Data Register 1和Data Register 0数据并解码 参考…

【Docker Compose】Docker Compose 的安装,使用以及实现微服务集群的部署

文章目录 前言&#xff1a;Docker 部署存在的问题一、 初识 Docker Compose1.1 什么是 Docker Compose1.2 在 CentOS 上安装 Docker Compose 二、深入了解 Docker Compose 文件2.1 Docker Compose 文件概述2.2 Docker Compose 文件详解2.3 示例&#xff1a;编写 Docker Compose…

哈希表(Hash Table)介绍

哈希表&#xff08;Hash Table&#xff09;介绍 哈希表&#xff08;Hash Table&#xff09;&#xff1a;也叫做散列表。是根据键值&#xff08;Key Value、关键码值&#xff09;直接进行访问的数据结构。 哈希表通过“键&#xff08;key&#xff09;”和“映射函数&#xff0…

<一>Qt斗地主游戏开发:开发环境搭建--VS2019+Qt5.15.2

1. 开发环境概述 对于Qt的开发环境来说&#xff0c;主流编码IDE界面一般有两种&#xff1a;Qt Creator或VSQt。为了简单起见&#xff0c;这里的操作系统限定为windows&#xff0c;编译器也通用VS了。Qt版本的话自己选择就可以了&#xff0c;当然VS的版本也是依据Qt版本来选定的…

Ubuntu Server CLI专业提示

基础 网络 获取所有接口的IP地址 networkctl status 显示主机的所有IP地址 hostname -I 启用/禁用接口 ip link set <interface> up ip link set <interface> down 显示路线 ip route 将使用哪条路线到达主机 ip route get <IP> 安全 显示已登录的用户 w…

问题记录 springboot 事务方法中使用this调用其它方法

原因: 因为代理对象中调用了原始对象的toString()方法,所以两个不同的对象打印出的引用是相同的

用于图像恢复的即插即用 ADMM:定点收敛和应用(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Java IDEA jackson序列化——查询父子类返回 亲测可行

Java IDEA jackson序列化——查询父子类返回 亲测可行 参考 把父类封装在一个对象中返回Response<List>,SiModelDo–BaseObject(各子类&#xff09;直接返回父类&#xff0c;不包含Response一层List&#xff1b; 直接返回可以 或者对象内包一层 JsonTypeInfo(use Json…