news 2026/5/1 10:27:53

AVL树的四种旋转操作用于在插入或删除节点导致二叉树失去平衡

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AVL树的四种旋转操作用于在插入或删除节点导致二叉树失去平衡

一、平衡二叉树(AVL 树)
设计目的:保证二叉排序树的高度为 $ O(\log_2 n) $,使插入、删除、查找等操作的最坏时间复杂度稳定在 $ O(\log_2 n) $。普通二叉排序树在极端情况下可能退化为链表,导致操作时间复杂度上升至 $ O(n) $。

核心定义:

  • 满足BST 性质:即对于任意节点,左子树所有节点值小于根节点值,右子树所有节点值大于根节点值。
  • 平衡条件:任一节点的左右子树高度差(称为平衡因子)的绝对值不超过 1。平衡因子 = 左子树深度 - 右子树深度,其值只能是 -1、0 或 1。

高度特性:
含有 $ n $ 个节点的 AVL 树,其最大高度约为 $ 1.44 \log_2 n $,远优于最坏情况下的 $ O(n) $,接近完全二叉树的理想高度 $ \log_2 n $。

为了维持平衡,在插入或删除节点后若出现不平衡(平衡因子变为 ±2),需通过旋转操作(单旋:LL、RR;双旋:LR、RL)进行调整,恢复平衡。


二、线索二叉树(Threaded Binary Tree)
设计目的:解决普通二叉树中无法高效获取某节点在中序遍历中的前驱和后继的问题。同时利用原本浪费的空指针域(n 个节点共有 $ n+1 $ 个空指针)来存储有用的线索信息,提高空间利用率和遍历效率。

实现方式:

  • 将空的左指针改为指向该节点在中序遍历中的前驱节点。
  • 将空的右指针改为指向该节点在中序遍历中的后继节点。
  • 引入两个标志位:
    • ltag:0 表示左指针指向左孩子,1 表示左指针为线索,指向前驱。
    • rtag:0 表示右指针指向右孩子,1 表示右指针为线索,指向后继。

节点结构示例(C语言风格):

structBTnode{intdata;structBTnode*left,*right;intltag;// 0: child, 1: thread (predecessor)intrtag;// 0: child, 1: thread (successor)};

通过中序线索化后,可以不使用栈或递归实现高效的中序遍历,直接沿线索访问下一个节点。
AVL树的四种旋转操作用于在插入或删除节点导致二叉树失去平衡(即某个节点的平衡因子变为±2)时,恢复其平衡性。这些旋转操作根据失衡节点与其子树中“过高”部分的位置关系分为四类:LL、RR、LR、RL。


一、四种旋转类型及适用场景

类型全称触发条件(以失衡节点为z场景描述
LL型Left-Leftz 的左子树比右子树高 2,且 z 的左孩子(y)的左子树更高(平衡因子为 +1 或 +2)失衡路径连续向左,形成“左偏左”结构
RR型Right-Rightz 的右子树比左子树高 2,且 z 的右孩子(y)的右子树更高(平衡因子为 -1 或 -2)失衡路径连续向右,“右偏右”结构
LR型Left-Rightz 的左子树过高,但 z 的左孩子的右子树更高先左后右的“Z”字形结构
RL型Right-Leftz 的右子树过高,但 z 的右孩子的左子树更高先右后左的镜像“Z”字形

📌核心思想:通过一次或两次旋转将“过高”的中间节点提升为新的根,使树重新满足 AVL 平衡条件。


二、旋转操作实现(C语言风格)

假设节点结构如下:

typedefstructAVLNode{intdata;structAVLNode*left;structAVLNode*right;intheight;// 存储当前节点高度,便于计算平衡因子}AVLNode;

辅助函数:获取高度与平衡因子

intmax(inta,intb){return(a>b)?a:b;}intheight(AVLNode*node){returnnode==NULL?0:node->height;}intgetBalance(AVLNode*node){returnnode==NULL?0:height(node->left)-height(node->right);}
1.右单旋(LL旋转)

适用于 LL 型失衡。

AVLNode*rotateRight(AVLNode*y){AVLNode*x=y->left;AVLNode*T2=x->right;// 执行右旋x->right=y;y->left=T2;// 更新高度(先更新子节点,再更新父节点)y->height=max(height(y->left),height(y->right))+1;x->height=max(height(x->left),height(x->right))+1;returnx;// 新的根节点}
2.左单旋(RR旋转)

适用于 RR 型失衡。

AVLNode*rotateLeft(AVLNode*x){AVLNode*y=x->right;AVLNode*T2=y->left;// 执行左旋y->left=x;x->right=T2;// 更新高度x->height=max(height(x->left),height(x->right))+1;y->height=max(height(y->left),height(y->right))+1;returny;// 新的根节点}
3.左右双旋(LR旋转)

先对左孩子左旋(RR),再对根右旋(LL)。

AVLNode*rotateLeftRight(AVLNode*z){z->left=rotateLeft(z->left);// 左孩子做一次左旋(RR)returnrotateRight(z);// 再整体右旋(LL)}
4.右左双旋(RL旋转)

先对右孩子右旋(LL),再对根左旋(RR)。

AVLNode*rotateRightLeft(AVLNode*z){z->right=rotateRight(z->right);// 右孩子做一次右旋(LL)returnrotateLeft(z);// 再整体左旋(RR)}

三、插入后的平衡调整逻辑示例

AVLNode*insert(AVLNode*node,intdata){// 1. 标准BST插入if(node==NULL){AVLNode*newNode=(AVLNode*)malloc(sizeof(AVLNode));newNode->data=data;newNode->left=newNode->right=NULL;newNode->height=1;returnnewNode;}if(data<node->data)node->left=insert(node->left,data);elseif(data>node->data)node->right=insert(node->right,data);elsereturnnode;// 不允许重复值// 2. 更新当前节点高度node->height=max(height(node->left),height(node->right))+1;// 3. 获取平衡因子intbalance=getBalance(node);// 4. 判断失衡类型并旋转调整// LL型if(balance>1&&data<node->left->data)returnrotateRight(node);// RR型if(balance<-1&&data>node->right->data)returnrotateLeft(node);// LR型if(balance>1&&data>node->left->data){node->left=rotateLeft(node->left);returnrotateRight(node);}// RL型if(balance<-1&&data<node->right->data){node->right=rotateRight(node->right);returnrotateLeft(node);}returnnode;// 已平衡,返回原节点}

总结记忆口诀

  • “同方向用单旋”:LL → 右旋,RR → 左旋
  • “异方向用双旋”:LR → 先左旋左孩子,再右旋根;RL → 先右旋右孩子,再左旋根
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 6:29:28

早停法(Early_Stopping)

目的:在模型达到最好效果的时候停止训练 设定一个监视值(monitor) 设定监视值不再发生改善前允许训练的最大次数 代码实现: 在model.fit之前添加: early_stop keras.callbacks.EarlyStopping(monitorval_loss, patience10) #模型训练中监视的值为val_loss,当模型在持续训练10个…

作者头像 李华
网站建设 2026/5/1 7:31:57

17、Linux 常用 Shell 命令与快捷方式指南

Linux 常用 Shell 命令与快捷方式指南 1. 用户实用工具 在日常的工作中,我们常常会有修改密码、更换 Shell、查找文件等需求。下面介绍一些实用的命令来满足这些需求。 1.1 修改密码:passwd 使用 passwd 命令可以修改用户密码。该命令是交互式的,会先要求输入当前密码…

作者头像 李华
网站建设 2026/4/30 15:13:45

22、Linux系统:备份、安装与管理全攻略

Linux系统:备份、安装与管理全攻略 在Linux系统的使用过程中,数据备份和软件安装是至关重要的环节。合理的数据备份可以防止数据丢失,而高效的软件安装则能让系统功能不断扩展。下面将详细介绍Linux系统的数据备份和软件安装的相关知识。 数据备份 数据备份是保障数据安全…

作者头像 李华
网站建设 2026/5/1 6:11:08

28、Debian 软件包创建与管理全解析

Debian 软件包创建与管理全解析 1. 本地 APT 仓库 在构建自定义 Debian 软件包时,需要一个 APT 仓库来分发这些软件包。虽然可以手动复制 DEB 文件并使用 dpkg 进行安装,但在涉及多台机器时,这种方法会变得非常繁琐。 设置 APT 仓库是一项简单的任务。无论 APT 的访问方式…

作者头像 李华
网站建设 2026/4/18 3:08:59

43、处理器调度与数据安全隐写技术解析

处理器调度与数据安全隐写技术解析 在计算机系统中,处理器调度和数据安全传输一直是重要的研究领域。下面将详细介绍处理器调度算法以及基于隐写术的数据安全传输方法。 自配置处理器调度窗口算法 在多处理器系统中,为了提高资源利用率,会采用自配置处理器调度窗口算法。…

作者头像 李华