平衡二叉树(AVL树):原理、常见算法及其应用

目录

引言

AVL树的基本概念

常见算法

插入节点

查找节点

删除节点

AVL树的应用场景

1. 数据库索引

2. 符号表

3. 字典和词汇表

4. 动态集合

5. GPS导航系统

6. 计算机辅助设计(CAD)

结论


引言

平衡二叉树(Balanced Binary Tree),特别是AVL树(Adelson-Velsky and Landis tree),是一种自平衡的二叉搜索树。它在每次插入或删除操作之后都会自动调整自身,以确保树的高度保持在尽可能小的状态。这种自我调整机制使得AVL树能够在保持较低的高度的同时,提供高效的查找、插入和删除操作。本文将从AVL树的基本概念出发,逐步介绍其原理、常见算法,并通过具体的Java代码示例来加深理解,最后探讨AVL树在算法中的实际应用场景。

AVL树的基本概念

AVL树是一种特殊的二叉搜索树,其特点是任何节点的两个子树的高度之差最多为1。这意味着AVL树始终保持在相对平衡的状态,从而保证了操作的高效性。

节点定义

class AVLTreeNode {int val;int height;AVLTreeNode left;AVLTreeNode right;AVLTreeNode(int x) {val = x;height = 1; // 新节点默认高度为1}
}

高度和平衡因子

  • 高度:节点的高度定义为该节点到其最远叶子节点路径上的边数。
  • 平衡因子:节点的平衡因子定义为其左子树的高度减去右子树的高度。

失衡

当我们在一个平衡二叉树上插入一个结点时,有可能会导致失衡,即出现平衡因子绝对值大于1       的结点,如下图,当插入结点后,其中key为53的结点失去了平衡,我们称该结点为失衡结点,我们必须重新调整树的结构,使之恢复平衡。

恢复平衡:

那如何去恢复平衡,使得二叉搜索树依然成立为一棵平衡树?先来看平衡调整的四种类型:

 举个例子:如第一个,当平衡二叉树为AB时,插入一个C结点,使得失衡了,失衡结点为A,此时因为C结点插入的位置为失衡结点的左孩子的左孩子,所以是LL型,以此类推。

为了恢复平衡,针对每一种都不一样,但目的都是调整为平衡的,且不能违背二叉搜索树的性质:如下图是每种失衡类型的解决方法,每个都不太一样,目的都是一样的,把key的值为中等的变为树的根,最小的放在左孩子,做大的放右孩子,通过这一目的,降低树的高度,也不用死记硬背。

 

常见算法

插入节点

插入新节点时,需要按照二叉搜索树的方式找到合适的位置,然后进行必要的旋转操作以恢复AVL树的平衡性。

例题:输入关键字序列(16,3,7,11 ,9,26,18,14,15)给出AVL树:

 

对应Java代码实现:

public class AVLTree {private AVLTreeNode root;// AVL树节点类private static class AVLTreeNode {int val;int height;AVLTreeNode left;AVLTreeNode right;AVLTreeNode(int x) {val = x;height = 1; // 新节点默认高度为1}}// 获取节点的高度private int getHeight(AVLTreeNode node) {if (node == null) {return 0;}return node.height;}// 获取节点的平衡因子private int getBalanceFactor(AVLTreeNode node) {if (node == null) {return 0;}return getHeight(node.left) - getHeight(node.right);}// 更新节点的高度private void updateHeight(AVLTreeNode node) {node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;}// 右旋private AVLTreeNode rotateRight(AVLTreeNode y) {AVLTreeNode x = y.left;AVLTreeNode T2 = x.right;// Perform rotationx.right = y;y.left = T2;// Update heightsupdateHeight(y);updateHeight(x);return x;}// 左旋private AVLTreeNode rotateLeft(AVLTreeNode x) {AVLTreeNode y = x.right;AVLTreeNode T2 = y.left;// Perform rotationy.left = x;x.right = T2;// Update heightsupdateHeight(x);updateHeight(y);return y;}// 插入节点public void insert(int value) {root = insertRecursive(root, value);}private AVLTreeNode insertRecursive(AVLTreeNode current, int value) {if (current == null) {return new AVLTreeNode(value);}if (value < current.val) {current.left = insertRecursive(current.left, value);} else if (value > current.val) {current.right = insertRecursive(current.right, value);} else {return current; // Value already exists}// Update height of this ancestor nodeupdateHeight(current);// Check balance factor to determine the rotationsint balanceFactor = getBalanceFactor(current);if (balanceFactor > 1) {if (value < current.left.val) {return rotateRight(current);} else if (value > current.left.val) {current.left = rotateLeft(current.left);return rotateRight(current);}}if (balanceFactor < -1) {if (value > current.right.val) {return rotateLeft(current);} else if (value < current.right.val) {current.right = rotateRight(current.right);return rotateLeft(current);}}return current;}// 打印AVL树public void printAVLTree() {printInOrder(root);System.out.println();}private void printInOrder(AVLTreeNode node) {if (node != null) {printInOrder(node.left);System.out.print(node.val + " ");printInOrder(node.right);}}// 主函数public static void main(String[] args) {AVLTree avlTree = new AVLTree();// 插入关键字序列avlTree.insert(16);avlTree.insert(3);avlTree.insert(7);avlTree.insert(11);avlTree.insert(9);avlTree.insert(26);avlTree.insert(18);avlTree.insert(14);avlTree.insert(15);// 打印AVL树avlTree.printAVLTree(); // 输出:3 7 9 11 14 15 16 18 26}
}

查找节点

查找特定值的节点时,从根节点开始,根据值与当前节点值的关系决定向左还是向右。

Java代码实现

boolean contains(int value) {return containsRecursive(root, value);
}private boolean containsRecursive(AVLTreeNode current, int value) {if (current == null) {return false;}if (value == current.val) {return true;}return value < current.val? containsRecursive(current.left, value): containsRecursive(current.right, value);
}

删除节点

删除节点时需要考虑三种情况:

  1. 节点是叶子节点。
  2. 节点有一个子节点。
  3. 节点有两个子节点。

Java代码实现

void delete(int value) {root = deleteRecursive(root, value);
}private AVLTreeNode deleteRecursive(AVLTreeNode current, int value) {if (current == null) {return current;}if (value < current.val) {current.left = deleteRecursive(current.left, value);} else if (value > current.val) {current.right = deleteRecursive(current.right, value);} else {// Node with only one child or no childif (current.left == null) {return current.right;} else if (current.right == null) {return current.left;}// Node with two children: Get the inorder successor (smallest in the right subtree)current.val = findMinValue(current.right);// Delete the inorder successorcurrent.right = deleteRecursive(current.right, current.val);}// If the node has only one child or no child, then it will be returned by above statements.if (current == null) {return current;}// Update the height of the current nodeupdateHeight(current);// Check balance factor to determine the rotationsint balanceFactor = getBalanceFactor(current);// Left Left Caseif (balanceFactor > 1 && getBalanceFactor(current.left) >= 0) {return rotateRight(current);}// Left Right Caseif (balanceFactor > 1 && getBalanceFactor(current.left) < 0) {current.left = rotateLeft(current.left);return rotateRight(current);}// Right Right Caseif (balanceFactor < -1 && getBalanceFactor(current.right) <= 0) {return rotateLeft(current);}// Right Left Caseif (balanceFactor < -1 && getBalanceFactor(current.right) > 0) {current.right = rotateRight(current.right);return rotateLeft(current);}return current;
}// Find the minimum value in a subtree
int findMinValue(AVLTreeNode node) {return node.left == null ? node.val : findMinValue(node.left);
}

AVL树的应用场景

1. 数据库索引

AVL树可以用于构建数据库的索引,以加速查询速度。

应用原理

  • 数据库记录的键值存储在AVL树的节点中。
  • 查询时,根据键值在树中查找对应的记录。
  • 插入和删除记录时,自动调整树的平衡,保持较低的高度。

场景描述

在数据库管理系统中,索引是提高查询效率的重要手段之一。当数据库需要频繁地按某个字段进行查询时,可以创建基于该字段的AVL树索引。这样,在执行查询操作时,可以迅速定位到指定键值所在的记录,而不需要全表扫描。AVL树的自平衡特性确保了索引结构的高效性,即使在频繁的插入和删除操作下也能保持良好的性能。

2. 符号表

在编程语言的编译器中,符号表用于跟踪变量声明和类型信息。

应用原理

  • 变量名称作为键值存储在AVL树中。
  • 变量的类型和其他相关信息作为键值对应的数据存储。
  • 编译器在处理源代码时,需要维护一个符号表来跟踪所有的变量声明及其属性。

场景描述

编译器在处理源代码时,需要维护一个符号表来跟踪所有的变量声明及其属性。AVL树可以有效地管理这些信息,因为编译器可以根据变量名称快速查找、插入或更新相应的信息。这有助于编译器在编译过程中进行类型检查和其他优化工作。AVL树的自平衡特性使得符号表能够在处理大型代码库时依然保持高效。

3. 字典和词汇表

在自然语言处理中,AVL树可用于构建词汇表或词典。

应用原理

  • 字符串作为键值存储在AVL树中。
  • 字符串的意义或其他附加信息作为键值对应的数据存储。
  • 在处理文本时,需要快速查找和更新词汇信息。

场景描述

在处理自然语言文本时,需要对文本中的词汇进行统计和分析。AVL树可以用于构建词汇表,其中词汇作为键值,出现频率等信息作为键值对应的数据。这有助于在处理文本时快速查找和更新词汇信息,从而提高文本处理的效率。AVL树的自平衡特性使得词汇表能够在处理大量词汇时依然保持高效。

4. 动态集合

AVL树可以用于实现动态集合,支持动态添加、删除元素并保持有序。

应用原理

  • 集合中的元素作为键值存储在AVL树中。
  • 插入新元素时,保持树的有序性。
  • 删除元素时,调整树以保持AVL树的性质。

场景描述

在需要动态管理一组有序元素的应用场景中,如任务队列或优先级队列,AVL树可以有效地支持元素的插入、删除操作,同时保持集合的有序性。这使得在处理动态变化的数据集合时更加高效和灵活。AVL树的自平衡特性使得动态集合在频繁的操作下依然保持良好的性能。

5. GPS导航系统

AVL树可以用于GPS导航系统中的路径规划算法。

应用原理

  • 路径规划算法需要快速查找和更新路径信息。
  • AVL树可以用于存储地理坐标信息,并快速查找最近的路径节点。

场景描述

在GPS导航系统中,路径规划算法需要快速查找和更新路径信息。AVL树可以用于存储地理坐标信息,并快速查找最近的路径节点。这有助于导航系统在实时更新路线时保持高效。AVL树的自平衡特性使得路径规划算法能够在处理大量地理数据时依然保持良好的性能。

6. 计算机辅助设计(CAD)

AVL树可以用于CAD系统中的图形对象管理。

应用原理

  • 图形对象的ID作为键值存储在AVL树中。
  • 图形对象的属性作为键值对应的数据存储。
  • CAD系统需要快速查找和更新图形对象的信息。

场景描述

在CAD系统中,需要管理大量的图形对象,并且经常需要快速查找和更新这些对象的信息。AVL树可以用于存储图形对象的ID,并快速查找对应的属性信息。这有助于CAD系统在处理复杂的设计时保持高效。AVL树的自平衡特性使得图形对象管理在处理大量数据时依然保持良好的性能。

结论

AVL树作为一种高效的数据结构,在计算机科学中有广泛的应用。通过自平衡机制,AVL树能够在保持较低的高度的同时,提供高效的查找、插入和删除操作。掌握AVL树的概念和相关算法对于深入理解计算机科学的核心知识至关重要。

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

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

相关文章

【JAVA开源】基于Vue和SpringBoot的甘肃非物质文化网站

本文项目编号 T 042 &#xff0c;文末自助获取源码 \color{red}{T042&#xff0c;文末自助获取源码} T042&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

英飞凌TC3xx -- Bootstrap Loader分析

目录 1.Bootstrap Loaders作用 2.CAN BSL详解 2.1 CAN BSL的时钟系统 2.2 CAN BSL流程 3.小结 英飞凌TC3xx的Platform Firmware章节里&#xff0c;提供了多种启动模式&#xff1a; Internal start from Flash&#xff1a;b111Alternate Boot Mode&#xff1a;b110Generic …

MySQL 数据库安装(详细教程)

文章目录 一、前言二、下载 MySQL2.1 安装包方式2.2 压缩包方式&#xff08;推荐&#xff09; 三、安装 MySQL3.1 解压 MySQL 文件3.2 配置环境变量3.3 初始化 data 目录3.4 安装 MySQL 服务3.5 开启 MySQL 服务3.6 修改 MySQL 密码 四、卸载 MySQL4.1 停止 MySQL 服务4.2 删除…

项目实战:Qt+OSG爆破动力学仿真三维引擎测试工具v1.1.0(加载.K模型,子弹轨迹模拟动画,支持windows、linux、国产麒麟系统)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/142454993 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、Op…

MongoDB-索引的使用和索引类型

目录 简介创建索引的方式索引的种类单列索引复合索引&#xff08;多列索引&#xff09;多键索引地理空间索引文本搜索索引Hash索引 索引属性 简介 MongoDB的索引种类还是不少的&#xff0c;因为它是个文档数据库&#xff0c;存储的数据种类杂七杂八的&#xff0c;针对MongoDB的…

MySQL学习笔记(持续更新中)

1、Mysql概述 1.1 数据库相关概念 三个概念&#xff1a;数据库、数据库管理系统、SQL 名称全称简称数据库存储数据的仓库&#xff0c;数据是有组织的进行存储DataBase&#xff08;DB&#xff09;数据库管理系统操纵和管理数据库的大型软件DataBase Mangement System&#xf…

输电线塔目标检测数据集yolo格式该数据集包括2644张输电线塔高清图像,该数据集已经过yolo格式标注,具有完整的txt标注文件和yaml配置文件。

输电线塔目标检测数据集yolo格式 该数据集包括2644张输电线塔高清图像&#xff0c;该数据集已经过yolo格式标注&#xff0c;具有完整的txt标注文件和yaml配置文件。 输电线塔目标检测数据集 数据集名称 输电线塔目标检测数据集&#xff08;Transmission Tower Object Detecti…

网页设计html心得

一&#xff0c;认识网页 说到网页&#xff0c;其实大家并不陌生 1.1网页究竟是什么&#xff1f; 网页主要由文字、图像和超链接等元素构成。当然&#xff0c;除了这些元素&#xff0c;网页中还可以包含音频、视频以及Flash等。 1.2网页是如何形成的呢&#xff1f; 1.特殊的…

Spring Boot 中的拦截器 Interceptors

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 前言 Spring Boot中的拦截器&#xff08;Interceptor&#xff09;是一种用于拦截和处理HTTP请求的机制&#xff0c;它基于Spring MVC框架中的HandlerInterceptor接口实现。拦截器允许在请求到达控制器&#…

git笔记之重置本地仓库所有分支和远程保持一致、工作区恢复干净,像刚clone下来一样

git笔记之重置本地仓库所有分支和远程保持一致、工作区恢复干净&#xff0c;像刚clone下来一样 code review! 文章目录 git笔记之重置本地仓库所有分支和远程保持一致、工作区恢复干净&#xff0c;像刚clone下来一样1.实现该功能的 Bash 脚本示例2.改进版&#xff1a;增加了gi…

微软宣布弃用面向企业的WSUS更新服务 仍然保留该服务但不再添加任何新功能

Windows Server Update Services 是微软面向企业推出的一项更新服务&#xff0c;该服务已经存在很多年&#xff0c;允许 IT 管理员控制内网设备的更新节奏。今年早些时候微软宣布将在 2025 年 4 月 18 日开始弃用 WSUS 驱动程序同步功能&#xff0c;因为大约只有 1/3 的 IT 管理…

大模型榜单汇总整理

大型语言模型&#xff08;LLM&#xff09;评估榜单提供了对不同模型性能的标准化比较&#xff0c;涵盖了从通用能力到特定领域应用的多个方面。这些榜单专注于评估模型在特定领域的应用能力&#xff0c;有助于开发者了解模型的优势和局限性&#xff0c;推动语言模型的发展和优化…

前端html+css+js 基础总结

​​​HTML 行级元素 标签分为行级元素与块级元素 行级元素占据区域由其显示内容决定&#xff0c;如span&#xff0c;img(图片)&#xff0c;<a></a>基本格式: <a href"链接" target"_blank"></a>用于跳转到其他网站&#xff0c…

镭射限高防外破预警装置-线路防外破可视化监控,安全尽在掌握中

镭射限高防外破预警装置-线路防外破可视化监控&#xff0c;安全尽在掌握中 在城市化浪潮的汹涌推进中&#xff0c;电力如同现代社会的生命之脉&#xff0c;其安全稳定运行直接关系到每一个人的生活质量和社会的整体发展。然而&#xff0c;随着建设的加速&#xff0c;电力设施通…

论文写作中的常见错误及规避策略

写论文&#xff0c;这个让无数学生闻风丧胆的挑战&#xff0c;可真是让人头大。 不管是初出茅庐的本科毕业论文&#xff0c;还是折腾得人头发都少了的硕士、博士论文&#xff0c;写作过程中的各种翻车场景简直就是论文写作的日常。 别慌&#xff0c;今天我就来当大家的论文救…

基于Python+SQLServer实现(界面)书店销售管理管理子系统

书店销售管理管理子系统 一、设 计 总 说 明 现在社会随着计算机技术迅速发展与技术的逐渐成熟&#xff0c;信息技术已经使人们的生活发生深刻的变化。生活中的各种服务系统也使人们在生活中的联系日常销售活动方式发生了很大的变化&#xff0c;让效率较低的手工操作成为过去…

vue3/Element-Plus/路由的使用

我们来实现一个简单的二级路由 1.准备主页和要配置的组件 主页面 <template><!-- 加载配置路由 --><RouterView></RouterView> </template><style scoped></style>组件1 <template><div>考试组件</div> </t…

【k8s】:DevOps 模式详解

1.什么是DevOps模式&#xff1f; DevOps 是当下非常火爆的一个概念&#xff0c;受到了很多互联网巨头的推崇。那么什么是 DevOps&#xff1f;它的全称是&#xff1a;集成开发与运维。至于它到底是干什么用的&#xff0c;为什么现在这么火爆&#xff0c;还得从源头说起。 1.1 …

vue3 vxe-grid 通过数据库返回的列信息,生成columns,并且其中有一列是img类型,进行slots的格式化处理。

1、一般我们写死的列信息的时候&#xff0c;会这样定义&#xff1a; 2、然后我们在template里面&#xff0c;这样这样写slots格式化部分&#xff1a; 这样表格中就会展示出一张图片&#xff0c;并且&#xff0c;我们点击了可以查看大图。 3、那么我们从数据库中返回的列&#…

二维矩阵的行、列、斜线特征(二维数组)

1. 行特征 二维 n*m 矩阵&#xff0c;用 x[i][j] 表示第 i 行第 j 列的元素。同一行的元素的 i 值是相同的。 例如&#xff0c;上图中绿色格子的数组元素分别是 x[4][1]&#xff0c;x[4][2]&#xff0c;x[4][3]&#xff0c;x[4][4]&#xff0c;x[4][5]&#xff0c;x[4][6]。 …