AVL树浅谈

前言

大家好,我是jiantaoyab,本篇文章给大家介绍AVL树。

基本概念

AVL树(Adelson-Velsky和Landis树)是一种自平衡的二叉搜索树,得名于其发明者G. M. Adelson-Velsky和E. M. Landis。在AVL树中,任何节点的两个子树的高度最大差别为1,因此它也被称为高度平衡树。

AVL树特点

  1. 二叉搜索树性质:AVL树本质上是一棵二叉搜索树,即每个节点的左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都大于该节点的值。
  2. 平衡条件:AVL树的每个节点的左子树和右子树的高度差之绝对值不超过1。这是AVL树与其他二叉搜索树的主要区别,保证了树的平衡性,从而优化了查找、插入和删除操作的性能。
  3. 平衡因子:每个节点都有一个平衡因子,定义为该节点的右子树高度减去左子树高度。在AVL树中,平衡因子的取值只能是-1、0或1。

模拟实现

AVL树节点定义

template<class K,class V>
struct AVLTreeNode
{AVLTreeNode<K, V> *_left;AVLTreeNode<K, V> *_right;AVLTreeNode<K, V> *_parent;pair<K,V> _kv;  //pair是将2个数据组合成一组数据int _bf; //balance factorAVLTreeNode(const pair<K, V>&kv):_left(nullptr), _right(nullptr), _parent(nullptr), _bf(0), _kv(kv){}};

插入操作

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;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//控制平衡//1、更新平衡因子 //2、异常,旋转平衡处理//只会影响这条路径,最坏更新到根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;}//旋转处理 //1:树平衡了//2:树的整体高度降了1else if (parent->_bf == 2 || parent->_bf == -2){//右单旋if (parent->_bf == -2 && cur->_bf == -1){RotateR(parent);}//左单旋else if (parent->_bf == 2 && cur->_bf == 1){RotateL(parent);}//双旋左右else if (parent->_bf == -2 && cur->_bf == 1){RotateLR(parent);}//双旋右左else if (parent->_bf == 2 && cur->_bf == -1){RotateRL(parent);}else{assert(false);}//旋转完之后不影响上面的,可以直接退出break;	}//插入之前,平衡因子有问题else{assert(false);}}return true;
}

旋转操作

右单旋

image-20240506110209062

	//右单旋void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;subL->_right = parent;//更新父节点if (subLR)subLR->_parent = parent;Node* parentParent = parent->_parent;parent->_parent = subL;//如果原来是根if (parent == _root){_root = subL;_root->_parent = nullptr;}//如果是别人的子树else{if (parentParent->_left == parent)parentParent->_left = subL;elseparentParent->_right = subL;subL->_parent = parentParent;}subL->_bf = parent->_bf = 0;}

左单旋

void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL){subRL->_parent = parent;}Node* parentParent = parent->_parent;subR->_left = parent;parent->_parent = subR;//原来是根if (_root == parent){_root = subR;subR->_parent = nullptr;}//原来是别人的子树else{if (parentParent->_left == parent)parentParent->_left = subR;elseparentParent->_right = subR;subR->_parent = parentParent;}subR->_bf = parent->_bf = 0;}

左右双旋

image-20240506123437496

void RotateLR(Node *parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == -1){parent->_bf = 1;subL->_bf = 0;}else if (bf == 1){parent->_bf = 0;subL->_bf = -1;}else{parent->_bf = subL->_bf = 0;}subLR->_bf = 0;}

右左双旋

void RotateRL(Node *parent)	{//   30 (parent)//  /   \//  a   90(subR)//      /   \     //    60(subRL)   d//   b  cNode *subR = parent->_right;Node *subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);//这里看图 变化后的图if (bf == 1){parent->_bf = -1;subR->_bf = 0;subRL->_bf = 0;}else if (bf == -1){parent->_bf = 0;subR->_bf = 1; subRL->_bf = 0;}else if (bf == 0){parent->_bf = 0;subR->_bf = 0;subRL->_bf = 0;}else{assert(false);}}

判断是不是AVL树

int Height(Node *root){if (root == NULL)return 0;int leftHeight = Height(root->_left);int rightHeight = Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}bool IsBalance(){return _IsBalance(_root);}//1.检查是不是搜索二叉树//2.检查每一课子树是不是AVL树bool _IsBalance(Node *root){if (root == NULL)return true;//当前树检查int leftHeight = Height(root->_left);int rightHeight = Height(root->_right);//平衡因子出问题if (rightHeight - leftHeight != root->_bf){cout << root->_kv.first << "NOW::" << root->_bf << endl;cout << root->_kv.first << "CORRECT::" << rightHeight - leftHeight << endl;return false;}//左右高度差不能超过2return abs(rightHeight - leftHeight) < 2 && _IsBalance(root->_left)&& _IsBalance(root->_right);}

AVL树性能

AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度,即O(log n)。

但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。

因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。

AVL树使用场景

  1. 数据库和文件系统的索引
    • 数据库系统经常需要快速检索、插入和删除记录。AVL树作为索引结构,可以加速这些操作,确保查询效率不会因为数据的不均匀分布而降低。
  2. 内存数据库
    • 对于需要快速响应的内存数据库,如Redis,使用AVL树可以确保数据访问的高效性。
  3. 字典或词汇查找
    • 在自然语言处理或文本编辑器中实现自动补全、拼写检查或同义词查找等功能时,AVL树可以提供快速的词汇查找和插入。
  4. 路由表查找
    • 在计算机网络中,路由器需要根据路由表快速查找最佳路径。AVL树可以确保路由查找的高效性。
  5. 搜索引擎
    • 搜索引擎在处理大量网页索引时需要快速检索和更新索引。AVL树可以帮助优化这些操作。
  6. 缓存系统
    • 在实现缓存替换策略(如LRU,即最近最少使用策略)时,AVL树可以帮助维护一个有序的缓存项列表,从而快速确定哪些项应该被替换。
  7. 事件处理系统
    • 在需要按时间顺序处理事件的系统(如日历应用或任务调度器)中,AVL树可以用于维护一个有序的事件列表。
  8. 科学计算和模拟
    • 在科学计算和模拟中,经常需要快速查找、插入或删除数据点。AVL树可以提供一个高效的数据结构来支持这些操作。
  9. 金融交易系统
    • 实现自动补全、拼写检查或同义词查找等功能时,AVL树可以提供快速的词汇查找和插入。

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

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

相关文章

OpenCV 入门(七)—— 身份证识别

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

四川景源畅信:抖音个人开通橱窗操作流程介绍详情

随着短视频平台的快速发展&#xff0c;抖音已经成为越来越多人展示自我、分享生活的舞台。而其中&#xff0c;个人橱窗功能则为内容创作者提供了一个展示和销售商品的窗口。如果你是一位想要在抖音上开通个人橱窗的创作者或商家&#xff0c;了解详细的操作流程是迈向成功的第一…

如何通过前端表格控件在10分钟内完成一张分组报表?

前言&#xff1a; 当今时代&#xff0c;报表作为信息化系统的重要组成部分&#xff0c;在日常的使用中发挥着关键作用。借助报表工具使得数据录入、分析和传递的过程被数字化和智能化&#xff0c;大大提高了数据的准确性及利用的高效性。而在此过程中&#xff0c;信息化系统能…

无经验计科应届生前端面试遇到的问题整理

js数据类型有几种&#xff0c;分别是 原始数据类型&#xff08;Primitive data types&#xff09;: 字符串&#xff08;String&#xff09;: 用于表示文本数据&#xff0c;使用单引号&#xff08;‘’&#xff09;或双引号&#xff08;“”&#xff09;括起来。 数字&#xff…

AArch64 内存管理

本文是对arm developer网站《Learn the architecture - AArch64 memory management Guide》的学习笔记&#xff08;Documentation – Arm Developer&#xff09; 一、背景概述 本文介绍了AArch64中的内存转换&#xff0c;这是内存管理的关键&#xff0c;它解释了虚拟地址如何转…

第3章 WebServer重构

3.1 重构原生Web服务框架 3.1.1 分析原生Web服务框架 在服务端代码的 ClientHandler 中&#xff0c;请求解析、处理请求、返回响应的代码混杂在一起&#xff0c;这样的设计会导致代码难以维护和理解。为了提高代码的可读性、可维护性和可扩展性&#xff0c;我们需要对这些代码…

ComfyUI搭建和注意事项for WIN[笔记]

下载ComfyUI(GitHub - comfyanonymous/ComfyUI: The most powerful and modular stable diffusion GUI, api and backend with a graph/nodes interface.) 从源码上搭建比较麻烦&#xff0c;一般不推荐&#xff0c;所以跑到release里面找一个下载。我的显卡是GeFore GTX 1050 …

飞腾E2000运行Zephyr操作系统

Phytium-Zephyr-SDK 1. 仓库介绍 1.1 本仓库特色 此项目是一个开源软件&#xff0c;专为物联网领域设计&#xff0c;基于Zephyr实时操作系统&#xff0c;针对Phytium系列CPU进行了专门的适配和应用开发。我们的目标是降低开发者的使用门槛&#xff0c;提供了部署文档和使用指…

同向双指针(滑动窗口)算法

209. 长度最小的子数组 这里的更新结果就题来定 class Solution {public int minSubArrayLen(int target, int[] nums) {int sum 0;int len 0;int f 0;for(int left 0, right 0; right < nums.length;){//求和sum nums[right];while(sum > target){//lenint t ri…

MLP实现fashion_mnist数据集分类(1)-模型构建、训练、保存与加载(tensorflow)

1、查看tensorflow版本 import tensorflow as tfprint(Tensorflow Version:{}.format(tf.__version__)) print(tf.config.list_physical_devices())2、fashion_mnist数据集下载与展示 (train_image,train_label),(test_image,test_label) tf.keras.datasets.fashion_mnist.l…

张大哥笔记:卖盗版网课,获利 100 万被抓

这几天刷视频&#xff0c;看到一个新闻&#xff0c;某大学生卖盗版网课&#xff0c;把别人2000多正版网课&#xff0c;以做活动名义售卖20元&#xff0c;获利100多万被抓。 下方图片来自&#xff1a;极目新闻 卖这种盗版网课&#xff0c;门槛低&#xff0c;成本低&#xff0c;…

解决3D模型只显示线框材质的方法---模大狮模型网

在3D建模和渲染过程中&#xff0c;正确的材质和纹理是呈现逼真效果的关键。然而&#xff0c;有时候用户可能会遇到一个常见问题&#xff0c;即3D模型在渲染或查看时只显示线框材质&#xff0c;而没有正确的表面纹理和颜色。本文将介绍解决这一问题的几种方法&#xff0c;帮助用…

7 人赚 960 亿美元,数字天才的首次独舞

巴菲特股东大会 一年一度的巴菲特股东大会如常召开&#xff0c;只不过这次坐在老爷子左手边的不再是老搭档查理芒格&#xff0c;而是钦点的未来继任者&#xff0c;格雷格阿贝尔。 随着芒格&#xff08;99岁&#xff09;的离开&#xff0c;巴菲特&#xff08;93岁&#xff09;也…

【.sh】Shell 脚本文件的基础内容

目录 &#x1f30a;1. 基础知识 &#x1f30a;2. 简单示例 &#x1f30d;2.1 示例一 输出"Hello, World!" &#x1f30d;2.2 示例二 输入输出创建 &#x1f30a;1. 基础知识 .sh文件是什么&#xff1f; .sh文件即 Shell 脚本文件&#xff0c;通常用来执行一系列…

Ranni: Taming Text-to-Image Diffusion for Accurate Instruction Following

Ranni: Taming Text-to-Image Diffusion for Accurate Instruction Following abstract 我们引入了一个语义面板作为解码文本到图像的中间件&#xff0c;支持生成器更好地遵循指令 Related work 最近的工作还通过包含额外的条件&#xff08;如补全掩码[15&#xff0c;45]、…

10 华三vlan技术介绍

AI 解析 -Kimi-ai Kimi.ai - 帮你看更大的世界 (moonshot.cn) 虚拟局域网&#xff08;VLAN&#xff09;技术是一种在物理网络基础上创建多个逻辑网络的技术。它允许网络管理员将一个物理网络分割成多个虚拟的局域网&#xff0c;这些局域网在逻辑上是隔离的&#xff0c;但实际…

【LeetCode刷题记录】105. 从前序与中序遍历序列构造二叉树 106. 从中序与后序遍历序列构造二叉树

105 从前序与中序遍历序列构造二叉树 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,1…

Pandas入门篇(三)-------数据可视化篇2(pandas-plot篇)

目录 概述一、格式1. 生成pandas.plotting对象来生成图表2. 调用plot()函数来生成图表3.支持的图表类型 二、单变量绘图常用图表1. 柱状图&#xff08;bar&#xff09;使用场景代码实现 2. 折线图&#xff08;line&#xff09;&#xff08;默认即为折线图&#xff09;适用场景代…

计算机毕业设计 | vue+springboot 在线花店后台管理系统(附源码)

1&#xff0c;绪论 1.1 项目背景 随着社会发展&#xff0c;网上购物已经成为我们日常生活的一部分。但是&#xff0c;至今为止大部分电商平台都是从人们日常生活出发&#xff0c;出售都是一些日常用品比如&#xff1a;食物、服装等等&#xff0c;并未发现一个专注于鲜花的电商…

从一到无穷大 #25 DataFusion:可嵌入,可扩展的模块化工业级计算引擎实现

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言架构总览与可扩展性Catalog and Data SourcesFront End逻辑计划与逻辑计划优化器…