【C++ AVL树】

文章目录

    • AVL树
      • AVL树的概念
      • AVL树节点的定义
      • AVL树的插入
      • AVL树的旋转
        • 右单旋
        • 左单旋
        • 左右双旋
        • 右左双旋
      • 代码实现
    • 总结

AVL树

AVL树的概念

二叉搜索树在顺序有序或接近有序的情况下,而插入搜索树将退化为单叉树,此时查找的时间复杂度为O(n),效率低下。
两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新节点后,保证每个节点的左右子树高度差的绝对值不超过1,即可降低树的高度,减少平均搜索长度。因此,AVL树也被叫做高度平衡二叉搜索树,插入,查找,删除在平均和最坏情况下的时间复杂度都是O( l o g 2 n log_2 n log2n)。

AVL树节点的定义

	template<class K, class V>struct AVLTreeNode{AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;pair<K, V> _kv;int _bf; //balance factor 平衡因子AVLTreeNode(const pair<K, V>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_bf(0){}};

注意:实现AVL树平衡因子不是必须的,只不过有了平衡因子帮助我们更便捷地控制整棵树。

AVL树的插入

  1. 根据二叉搜索树的规则插入新节点
bool Insert(const pair<K, V> & kv){root为空,特殊处理if (_root == nullptr){_root = new Node(kv);return true;}Node* curr = _root;Node* parent = nullptr;while (curr){if (curr->_kv.first < kv.first){parent = curr;curr = curr->_right;}else if (curr->_kv.first > kv.first){parent = curr;curr = curr->_left;}else{return false;}}将新节点和其父亲节点链接起来Node* newnode = new Node(kv);if (parent->_kv.first < kv.first)parent->_right = newnode;elseparent->_left = newnode;newnode->_parent = parent;......}
  1. 不断向上更新平衡因子
    1. 当前平衡因子为0,说明插入之前平衡因子为1 / -1,插入之后不改变树的高度,不会影响其他祖先节点,此时更新结束。
    2. 当前平衡因子为1 / -1,说明插入之前平衡因子为0,插入之后当前节点地高度发生变化,会影响其他祖先节点,但是不违反规则,需要向上对祖先节点进行更新,直至当前节点为root。
    3. 当前平衡因子为 2 / -2,此时当前节点所在地子树违反了平衡规则,需要进行处理–>旋转。
while (parent)
{if (parent->_left == newnode){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){旋转处理}else{assert(false);}
}

AVL树的旋转

右单旋

在这里插入图片描述

void RotatoR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;subL->_right = parent;Node* ppnode = parent->_parent;parent->_parent = subL;if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (ppnode->_left == parent)ppnode->_left = subL;elseppnode->_right = subL;subL->_parent = ppnode;}parent->_bf = 0;subL->_bf = 0;
}
左单旋

在这里插入图片描述

void RotatoL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;Node* ppnode = parent->_parent;parent->_parent = subR;if (parent == _root){_root = subR;subR->_parent = nullptr;}else{if (ppnode->_left == parent)ppnode->_left = subR;elseppnode->_right = subR;subR->_parent = ppnode;}parent->_bf = 0;subR->_bf = 0;
}
左右双旋

在这里插入图片描述
旋转之前,45的平衡因子可能是-1/0/1,旋转完成之后,根据情况对其他节点的平衡因子进行调整

void RotatoLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotatoL(subL);RotatoR(parent);subLR->_bf = 0;if (bf == 0){subL->_bf = 0;parent->_bf = 0;}else if (bf == 1){subL->_bf = -1;parent->_bf = 0;}else if (bf == -1){subL->_bf = 0;parent->_bf = 1;}
}
右左双旋

在这里插入图片描述

void RotatoRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;subRL->_bf = 0;RotatoR(subR);RotatoL(parent);if (bf == 0){subR->_bf = 0;parent->_bf = 0;}else if (bf == 1){subR->_bf = 0;parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;parent->_bf = 0;}
}

代码实现

namespace xxx
{template<class K, class V>struct AVLTreeNode{AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;pair<K, V> _kv;int _bf; //balance factor 平衡因子AVLTreeNode(const pair<K, V>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_bf(0){}};template<class K, class V>class AVLTree{typedef AVLTreeNode<K, V> Node;public:bool Insert(const pair<K, V> & kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* curr = _root;Node* parent = nullptr;while (curr){if (curr->_kv.first < kv.first){parent = curr;curr = curr->_right;}else if (curr->_kv.first > kv.first){parent = curr;curr = curr->_left;}else{return false;}}Node* newnode = new Node(kv);if (parent->_kv.first < kv.first)parent->_right = newnode;elseparent->_left = newnode;newnode->_parent = parent;while (parent){if (parent->_left == newnode){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){RotatoL(parent);}else if (parent->_bf == -2 && newnode->_bf == -1){RotatoR(parent);}else if (parent->_bf == -2 && newnode->_bf == 1){RotatoLR(parent);}else if (parent->_bf == 2 && newnode->_bf == -1){RotatoRL(parent);}else{assert(false);}break;}else{assert(false);}}return true;}void RotatoL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;Node* ppnode = parent->_parent;parent->_parent = subR;if (parent == _root){_root = subR;subR->_parent = nullptr;}else{if (ppnode->_left == parent)ppnode->_left = subR;elseppnode->_right = subR;subR->_parent = ppnode;}parent->_bf = 0;subR->_bf = 0;}void RotatoR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;subL->_right = parent;Node* ppnode = parent->_parent;parent->_parent = subL;if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (ppnode->_left == parent)ppnode->_left = subL;elseppnode->_right = subL;subL->_parent = ppnode;}parent->_bf = 0;subL->_bf = 0;}void RotatoLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotatoL(subL);RotatoR(parent);subLR->_bf = 0;if (bf == 0){subL->_bf = 0;parent->_bf = 0;}else if (bf == 1){subL->_bf = -1;parent->_bf = 0;}else if (bf == -1){subL->_bf = 0;parent->_bf = 1;}}void RotatoRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;subRL->_bf = 0;RotatoR(subR);RotatoL(parent);if (bf == 0){subR->_bf = 0;parent->_bf = 0;}else if (bf == 1){subR->_bf = 0;parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;parent->_bf = 0;}}void InOrder(){_InOrder(_root);cout << endl;}bool IsAVLTree(){return _IsAVLTree(_root);}private:bool _IsAVLTree(Node* root){if (root == nullptr)return true;int leftH = Height(root->_left);int rightH = Height(root->_right);return abs(leftH - rightH) <= 1&& _IsAVLTree(root->_left)&& _IsAVLTree(root->_right);}int Height(Node* node){if (node == nullptr)return 0;int leftH = Height(node->_left);int rightH = Height(node->_right);return 1 + max(leftH, rightH);}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.second << ' ';_InOrder(root->_right);}Node* _root = nullptr;};
}

总结

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

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

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

相关文章

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:颜色渐变)

设置组件的颜色渐变效果。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 linearGradient linearGradient(value: { angle?: number | string; direction?: GradientDirection; colors: Array; repea…

mamba-ssm安装building wheel卡着不动后error...避坑解决方法

文章目录 方法1、下载whl文件到本地后pip install安装成功后验证&#xff1a; 方法2、拉取Docker镜像 对于项目中用到MambaIR的小伙伴&#xff0c;需要pip安装 causal_conv1d和 mamba-ssm两个包及其依赖&#xff1a; torch packing transformersMambaIR-Github主页&#xff0…

【C++】vector的使用及其模拟实现

这里写目录标题 一、vector的介绍及使用1. vector的介绍2. 构造函数3. 遍历方式4. 容量操作及空间增长问题5. 增删查改6. vector二维数组 二、vector的模拟实现1. 构造函数2. 迭代器和基本接口3. reserve和resize4. push_back和pop_back5. insert和erase5. 迭代器失效问题5. 浅…

【Java】基础算法练习题

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 目录 基础算法练习题&#x1f680;1. 两数之和…

Django 管网项目 三

Django 官网文档 ​​Writing your first Django app, part 2 | Django documentation | Django 本文内容涉及创建视图 View&#xff0c;路由&#xff0c;和模版。并对内容进行渲染。 创建视图 在我们的投票应用中&#xff0c;我们需要下列几个视图&#xff1a; 问题索引页—…

ChatGPT支持下的PyTorch机器学习与深度学习技术应用

近年来&#xff0c;随着AlphaGo、无人驾驶汽车、医学影像智慧辅助诊疗、ImageNet竞赛等热点事件的发生&#xff0c;人工智能迎来了新一轮的发展浪潮。尤其是深度学习技术&#xff0c;在许多行业都取得了颠覆性的成果。另外&#xff0c;近年来&#xff0c;Pytorch深度学习框架受…

相关知识1111

一、 店铺编号和相关负责人 1、天猫兄弟、锦格 京东凡越 福林哥 如萍姐 2、京东锦格 天猫凡越 林森 雷佳华 3、天猫从简 京东从简 孔哥 4、抖音锦格 拼多多凡越 鸿哥 不知道哪个店铺编号&#xff1a;0 二、天猫京东聊天界面快捷搜索商品 1、 天猫只能根据标题搜索 2、京东是…

神经网络之万能定理python-pytorch实现,可以拟合任意曲线

神经网络之万能定理python-pytorch实现&#xff0c;可以拟合任意曲线 博主&#xff0c;这几天一直在做这个曲线拟合的实验&#xff0c;讲道理&#xff0c;网上可能也有很多这方面的资料&#xff0c;但是博主其实试了很多&#xff0c;效果只能对一般的曲线还行&#xff0c;稍微…

java之抽象类

什么是抽象类&#xff1f; 抽象就是不能具体化&#xff0c;不能实例化 作为父类&#xff0c;让子类去实现 abstract修饰类就是抽象类 abstract修饰方法就是抽象方法修饰符 abstract class 类名{修饰符 abstract 返回值类型 方法名(形参列表); }public abstract class A {//不…

CTFHUB--文件包含漏洞--RCE

文件包含漏洞 文件包含漏洞也是一种注入型漏洞&#xff0c;其本质就是输入一段用户能够控制的脚本或者代码&#xff0c;并让服务端执行。有时候由于网站功能需求&#xff0c;会让前端用户选择要包含的文件&#xff0c;而开发人员又没有对要包含的文件进行安全考虑&#xff0c;…

CSS【详解】居中对齐 (水平居中 vs 垂直居中)

水平居中 内部块级元素的宽度要小于容器(父元素) 方案一&#xff1a;文本居中对齐&#xff08;内联元素&#xff09; 限制条件&#xff1a;仅用于内联元素 display:inline 和 display: inline-block; 给容器添加样式 text-align:center<!DOCTYPE html> <html lang&q…

裴蜀定理(Bézout’s identity)

裴蜀定理&#xff08;Bzout’s identity&#xff09;是一个数论定理&#xff0c;也称为贝祖等式。它表明&#xff0c;对于任意给定的两个整数 a a a 和 b b b&#xff0c;存在整数 x x x 和 y y y&#xff0c;使得它们满足以下方程&#xff1a; a x b y gcd ⁡ ( a , b )…

【简略知识】项目开发中,VO,BO,PO,DO,DTO究竟是何方妖怪?

前言 在项目开发中&#xff0c;是否需要定义VO&#xff08;视图对象&#xff09;&#xff0c;BO&#xff08;业务对象&#xff09;&#xff0c;PO&#xff08;持久化对象&#xff09;&#xff0c;DO&#xff08;领域对象&#xff09;&#xff0c;DTO&#xff08;数据传输对象&…

CKKS EXPLAINED, PART 3: ENCRYPTION AND DECRYPTION

CKKS EXPLAINED, PART 3: ENCRYPTION AND DECRYPTION Introduction 在之前的文章中&#xff0c;CKKS解释了第二部分&#xff1a;完整的编码和解码&#xff0c;我们看到了如何实现CKKS的编码器和解码器&#xff0c;这使我们能够将向量转换为多项式&#xff0c;反之亦然。这一步…

笨办法学 Python3 第五版(预览)(三)

原文&#xff1a;Learn Python the Hard Way, 5th Edition (Early Release) 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 练习 30&#xff1a;假如 这是你将要输入的下一个 Python 脚本&#xff0c;它向你介绍了if语句。输入这个代码&#xff0c;确保它能够完美运行…

怎么快速编辑视频

背景&#xff1a;怎么简单快速编辑视频 利用FFmpeg功能&#xff0c;简单快速编辑视频&#xff0c;如按9:16提前剪切视频、替换背景音乐。 下载FFmpeg&#xff1a;https://ffmpeg.org/download.html 将FFmpeg的路径添加到环境变量中&#xff1a; Windows&#xff1a;在系统的环…

Home-credit海外贷款信贷产品源码/线上贷款产品大全/贷款平台软件源码/海外借贷平台

测试环境&#xff1a;Linux系统CentOS7.6、宝塔、PHP7.3、MySQL5.6&#xff0c;根目录public&#xff0c;伪静态laravel5&#xff0c;开启ssl证书 语言&#xff1a;中文简体、英文 laravel框架的程序有点多&#xff0c;这个团队估计主要就是搞laravel开发的&#xff0c;基本上…

前端架构: 脚手架通用框架封装之脚手架注册和命令注册开发(教程二)

脚手架注册和命令注册 1 &#xff09;脚手架的注册 接上文&#xff0c;仍旧在 abc-cli 项目中参考&#xff1a;https://blog.csdn.net/Tyro_java/article/details/136381086之前初始化的时候&#xff0c;使用的是 yargs, 现在我们想要使用 commander在cli包中安装 commander $…

2024 最新版 Compose material3 下拉刷新

2024 最新版 Compose material3 下拉刷新&#xff0c;版本 > 1.2.0 的 compose material3 已经更新了下拉刷新组件的 Api 见 https://developer.android.com/jetpack/androidx/releases/compose-material3?hlzh-cn#1.2.0 使用方法&#xff1a;https://developer.android.…

YOLOv9独家原创改进|增加SPD-Conv无卷积步长或池化:用于低分辨率图像和小物体的新 CNN 模块

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; 一、文章摘要 卷积神经网络(CNNs)在计算即使觉任务中如图像分类和目标检测等取得了显著的成功。然而&#xff0c;当图像分辨率较低或物体较小时&…