news 2026/1/14 11:43:47

在平衡二叉树(AVL 树)中,双旋转和删除操作是维持树结构平衡的关键机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在平衡二叉树(AVL 树)中,双旋转和删除操作是维持树结构平衡的关键机制

在平衡二叉树(AVL 树)中,双旋转和删除操作是维持树结构平衡的关键机制。当插入或删除节点导致树失衡时,需根据具体失衡类型进行相应的旋转调整。

1. 双旋转平衡处理

先左后右双旋转(LR 型)
  • 场景:节点 A 的平衡因子为 1(左子树高),在其左子树的右子树中插入新节点,使 A 的平衡因子变为 2,树失衡。
  • 操作步骤
    1. 对 A 的左子节点 B 的右子树进行左旋(即以 B 的右子树根节点 C 为轴向左旋转),将插入点“上提”,转化为 LL 型;
    2. 再对节点 A 进行右旋,恢复整体平衡。
  • 本质:通过两次旋转将插入引发的“折线型”不平衡转变为直线型并修复。
先右后左双旋转(RL 型)
  • 场景:节点 A 的平衡因子为 -1(右子树高),在其右子树的左子树中插入新节点,使 A 的平衡因子变为 -2。
  • 操作步骤
    1. 对 A 的右子节点 D 的左子树进行右旋(以 E 为轴向右旋转);
    2. 再对 A 进行左旋,恢复平衡。
  • 目的:消除“折线型”失衡,转化为 RR 型后再处理。

2. 平衡二叉树的删除操作

  • 核心逻辑

    • 若被删节点有两个子树,则用其左子树中序遍历的最后一个节点(即左子树的最大值)或右子树中序遍历的第一个节点(即右子树的最小值)替代之,从而将问题转化为删除只有一个子树的节点。
    • 删除后,从被删节点位置沿路径向上回溯至根节点,逐层更新各节点的平衡因子
    • 若某节点的平衡因子变为 ±2,则判断其失衡类型(LL、RR、LR、RL),执行对应单旋或双旋操作重新平衡。
    • 旋转后可能缩短子树高度,需继续检查祖先节点是否仍平衡,直至整条路径处理完毕。
  • 时间复杂度:每次插入/删除最多引发 O(log n) 次旋转(实际通常仅需常数次),整体仍保持 O(log n)。


补充说明

AVL 树通过严格的平衡条件确保查找效率最优,但频繁的旋转增加了插入删除开销,适用于查询远多于修改的场景。后续如红黑树等结构在平衡性与维护成本之间做了折中。

# 示例:模拟 LR 型双旋转(简化示意)defrotate_LR(A):B=A.left C=B.right# 左旋 B 的右子树B.right=C.left C.left=B A.left=C# 右旋 Areturnrotate_right(A)defrotate_right(A):B=A.left A.left=B.right B.right=AreturnB

判断一个节点属于 LL、RR、LR 或 RL 失衡类型,关键在于分析失衡节点的平衡因子以及其子树中导致失衡的插入(或删除)位置。以下是具体判断方法:


1. 前提条件

  • 某节点 A 的平衡因子变为+2 或 -2,说明以 A 为根的子树失衡。
  • 需根据 A 的子树结构进一步判断是哪种类型。

2. 判断规则

(1)LL 型(Left-Left)
  • 表现:A 的平衡因子为+2,且其左子节点 B 的平衡因子为+1
  • 原因:新节点插入在 A 的左子树的左子树
  • 形态
A (+2) / B (+1) / C
  • 处理方式:对 A 执行右旋(单旋)

(2)RR 型(Right-Right)
  • 表现:A 的平衡因子为-2,且其右子节点 D 的平衡因子为-1
  • 原因:新节点插入在 A 的右子树的右子树
  • 形态
A (-2) \ D (-1) \ E
  • 处理方式:对 A 执行左旋(单旋)

(3)LR 型(Left-Right)
  • 表现:A 的平衡因子为+2,但其左子节点 B 的平衡因子为-1
  • 原因:新节点插入在 A 的左子树的右子树
  • 形态
A (+2) / B (-1) \ C
  • 处理方式:先对 B 做左旋,再对 A 做右旋(双旋转)

(4)RL 型(Right-Left)
  • 表现:A 的平衡因子为-2,但其右子节点 D 的平衡因子为+1
  • 原因:新节点插入在 A 的右子树的左子树
  • 形态
A (-2) \ D (+1) / C
  • 处理方式:先对 D 做右旋,再对 A 做左旋(双旋转)

总结口诀(便于记忆):

类型平衡因子(根)子节点平衡因子插入路径旋转方式
LL+2+1左 → 左右旋(单)
RR-2-1右 → 右左旋(单)
LR+2-1左 → 右先左后右(双)
RL-2+1右 → 左先右后左(双)

⚠️ 注意:删除操作也可能引发上述失衡,判断方式相同,但可能需要沿路径持续调整多个祖先节点。

# 判断失衡类型的伪代码示意defget_balance_type(node):bf=get_balance_factor(node)ifbf==2:left_bf=get_balance_factor(node.left)ifleft_bf==1:return"LL"elifleft_bf==-1:return"LR"elifbf==-2:right_bf=get_balance_factor(node.right)ifright_bf==-1:return"RR"elifright_bf==1:return"RL"return"Balanced"

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/11 14:51:52

编译器升级必看,Clang 17性能优化避坑与增效秘籍

第一章:Clang 17性能优化的背景与意义随着现代软件系统对运行效率和资源利用率的要求日益提升,编译器作为连接高级语言与机器代码的核心工具,其优化能力直接影响程序的执行性能。Clang 17 作为 LLVM 项目的重要组成部分,在编译速度…

作者头像 李华
网站建设 2026/1/7 3:35:28

【Linux C/C++开发必看】:GCC 14调试黑科技,你真的会用吗?

第一章:GCC 14调试功能概览GCC 14 作为 GNU 编译器集合的最新重要版本,在调试支持方面引入了多项增强功能,显著提升了开发者在复杂项目中的诊断效率。这些改进不仅优化了调试信息的生成质量,还增强了与主流调试工具(如…

作者头像 李华
网站建设 2026/1/9 16:18:27

std::future终于支持超时了,C++开发者必须掌握的3个新用法

第一章:std::future终于支持超时了,C开发者必须掌握的3个新用法C标准库中的 std::future 长期以来缺乏对超时机制的原生支持,开发者不得不依赖轮询或第三方库实现。随着 C20 引入 wait_for 和 wait_until 的完善支持,std::future …

作者头像 李华
网站建设 2026/1/11 9:28:56

一点资讯个性化推送:精准触达潜在OCR技术用户群体

一点资讯个性化推送:精准触达潜在OCR技术用户群体 在内容平台日益智能化的今天,用户的每一次上传、截图或拍照,都可能隐藏着未被挖掘的兴趣信号。尤其当一张包含文字信息的图片出现在一点资讯这类平台上时——无论是新闻截图、外文文章还是证…

作者头像 李华
网站建设 2026/1/12 8:52:50

JavaScript调用HunyuanOCR API接口的示例代码分享

JavaScript调用HunyuanOCR API接口的示例代码分享 在当今智能办公与文档数字化需求激增的背景下,如何快速、准确地从图像中提取文字信息,已成为前端开发者面临的一项高频挑战。传统OCR工具要么依赖复杂的本地库(如Tesseract)&…

作者头像 李华
网站建设 2026/1/12 18:06:12

C++26即将发布:std::future支持超时,你准备好了吗?

第一章:C26 std::future 超时机制概述C26 对 std::future 的超时处理机制进行了标准化增强,旨在解决长期以来开发者在异步编程中面对的阻塞与超时控制难题。新标准引入了更一致、可预测的等待策略,使 wait_for 和 wait_until 成为所有 std::f…

作者头像 李华