当前位置: 首页 > news >正文

平衡二叉树的奥秘:AVLTree高效实现解析

平衡二叉树(AVLTree)

平衡二叉树(AVLTree)是一种自平衡二叉搜索树,由 Adelson-Velsky 和 Landis 于 1962 年提出。它通过维护每个节点的平衡因子(定义为左子树高度减去右子树高度)来确保树的高度平衡,即任意节点的平衡因子绝对值不超过 1($|\text{balance}| \leq 1$)。这保证了查找、插入和删除操作的时间复杂度均为 $O(\log n)$,适用于需要高效动态数据管理的场景。

核心概念
  1. 平衡因子:对于节点 $N$,平衡因子 $\text{balance}(N) = \text{height}(\text{left_subtree}) - \text{height}(\text{right_subtree})$。平衡条件是 $|\text{balance}(N)| \leq 1$。
  2. 高度更新:插入或删除节点后,需递归更新节点高度(高度定义为从该节点到最深叶子节点的路径长度)。
  3. 旋转操作:当平衡因子绝对值大于 1 时,执行旋转以恢复平衡:
    • 右旋(Right Rotation):用于“左左”不平衡情况(新节点插入在左子树的左子树)。
    • 左旋(Left Rotation):用于“右右”不平衡情况(新节点插入在右子树的右子树)。
    • 左右旋(Left-Right Rotation):先左旋左子节点,再右旋当前节点,用于“左右”情况。
    • 右左旋(Right-Left Rotation):先右旋右子节点,再左旋当前节点,用于“右左”情况。
C++ 实现

以下是 AVLTree 的完整 C++ 实现,包括节点结构、插入操作和旋转逻辑。代码使用递归实现插入,并处理所有四种不平衡情况。

#include <iostream> #include <algorithm> using namespace std; // 定义 AVL 树节点 class TreeNode { public: int key; // 节点键值 TreeNode* left; // 左子节点指针 TreeNode* right; // 右子节点指针 int height; // 节点高度(从该节点到最深叶子节点的边数) TreeNode(int k) : key(k), left(nullptr), right(nullptr), height(1) {} }; // 定义 AVL 树类 class AVLTree { private: TreeNode* root; // 根节点指针 // 辅助函数:获取节点高度(空节点高度为 0) int height(TreeNode* node) { if (node == nullptr) return 0; return node->height; } // 辅助函数:计算平衡因子 int getBalance(TreeNode* node) { if (node == nullptr) return 0; return height(node->left) - height(node->right); } // 右旋操作(用于左左不平衡) TreeNode* rightRotate(TreeNode* y) { TreeNode* x = y->left; TreeNode* T2 = x->right; // 执行旋转 x->right = y; y->left = T2; // 更新高度(先更新子节点 y,再更新父节点 x) y->height = max(height(y->left), height(y->right)) + 1; x->height = max(height(x->left), height(x->right)) + 1; return x; // 返回新根节点 } // 左旋操作(用于右右不平衡) TreeNode* leftRotate(TreeNode* x) { TreeNode* y = x->right; TreeNode* 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; return y; // 返回新根节点 } // 递归插入节点 TreeNode* insertNode(TreeNode* node, int key) { // 步骤 1: 正常二叉搜索树插入 if (node == nullptr) { return new TreeNode(key); // 创建新节点 } if (key < node->key) { node->left = insertNode(node->left, key); } else if (key > node->key) { node->right = insertNode(node->right, key); } else { return node; // 键值重复,不插入 } // 步骤 2: 更新当前节点高度 node->height = 1 + max(height(node->left), height(node->right)); // 步骤 3: 计算平衡因子 int balance = getBalance(node); // 步骤 4: 如果不平衡,执行旋转 // 左左情况(新节点在左子树的左子树) if (balance > 1 && key < node->left->key) { return rightRotate(node); } // 右右情况(新节点在右子树的右子树) if (balance < -1 && key > node->right->key) { return leftRotate(node); } // 左右情况(新节点在左子树的右子树) if (balance > 1 && key > node->left->key) { node->left = leftRotate(node->left); return rightRotate(node); } // 右左情况(新节点在右子树的左子树) if (balance < -1 && key < node->right->key) { node->right = rightRotate(node->right); return leftRotate(node); } return node; // 返回未修改或调整后的节点 } // 中序遍历(用于测试) void inOrder(TreeNode* node) { if (node == nullptr) return; inOrder(node->left); cout << node->key << " "; inOrder(node->right); } public: AVLTree() : root(nullptr) {} // 公共插入接口 void insert(int key) { root = insertNode(root, key); } // 中序遍历接口 void printInOrder() { inOrder(root); cout << endl; } }; int main() { AVLTree tree; // 测试插入操作 tree.insert(10); tree.insert(20); tree.insert(30); tree.insert(40); tree.insert(50); tree.insert(25); cout << "中序遍历结果: "; tree.printInOrder(); // 输出应有序: 10 20 25 30 40 50 return 0; }

https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKP0
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKPG
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKPY
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKQC
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKQO
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKRP
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKS3
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKSM
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKTG
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKTR
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKUA
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKUQ
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKV7
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKW1
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKWH
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKWX
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKXJ
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKY2
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKYJ
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKZ1
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAKZP
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAL05
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAL0J
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAL0V
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAL17
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAL1H
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAL1X
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAL2A
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAL2I
https://gitee.com/Guhuitao/resjtrhtr/issues/IJAL2R

代码解析
  1. 节点结构TreeNode包含键值、左右子节点指针和高度。
  2. 高度管理height()函数处理空节点情况,确保高度计算正确。
  3. 插入逻辑
    • 递归插入新节点。
    • 更新节点高度。
    • 检查平衡因子,根据四种情况执行旋转。
  4. 旋转操作
    • rightRotateleftRotate通过调整指针恢复平衡,并更新高度。
  5. 测试main函数演示插入序列,中序遍历输出有序序列。
性能与应用
  • 时间复杂度:所有操作(插入、删除、查找)均为 $O(\log n)$。
  • 优势:适用于数据库索引、实时系统等需要快速动态更新的场景。
  • 扩展:删除操作类似插入,但更复杂;需先删除节点,再递归平衡树。完整实现可添加删除方法。

通过维护平衡,AVLTree 在动态数据集中提供稳定性能,是 C++ 中实现高效搜索的理想选择。

http://www.jsqmd.com/news/668977/

相关文章:

  • 【2024 AGI前沿突破】:斯坦福+DeepMind联合验证的4类自主学习范式对比报告
  • 驾驭 Claude 的智能(Harnessing Claude’s intelligence)
  • 贵阳毕业季求职指南|1200万毕业生涌入,这5类岗位和6家公司最值得关注 - 精选优质企业推荐官
  • TypeScript的template literal types实现SQL查询的类型安全
  • 【AGI军事伦理红区预警】:20年国防科技专家首次公开3大不可逾越的AI作战红线
  • 划时代claude-opus-4-7重磅来袭,DMXAPI平台特惠开放,降低 AI 使用成本
  • NLP学习笔记13:BERT系列模型——从预训练到 RoBERTa 与 ALBERT
  • CREO实战宝典:从阵列到骨架模型,解锁十大经典零件设计全流程(曲柱、风扇叶、齿轮参数化、油缸等)
  • 告别DrawCall卡顿!Unity 2022最新Sprite Atlas图集打包保姆级教程(含旧版本迁移指南)
  • 鸣潮自动化终极指南:如何用ok-ww实现智能自动战斗与资源收集
  • 2026年,泉州创业者资源对接会哪个好用?
  • 贵阳销售岗位火热招聘,这5家企业正在疯狂抢人 - 精选优质企业推荐官
  • c# 获取CAD已加载的线型 并且在对话框的下拉列表显示出来
  • 从STRIDE到EVITA:聊聊车载网络威胁建模中,那个更适合你的安全属性模型
  • 告别龟速下载!Hugging Face预训练模型(BERT/RoBERTa)手动下载与本地加载保姆级教程
  • 贵阳找工作必看:2026年销售岗位大盘点,为什么AI营销和顾问型销售更值得选? - 精选优质企业推荐官
  • 解决VisualStudio2026中文打印报错或者乱码
  • UE4/UE5委托实战避坑:从触发器交互到UI响应,手把手教你四种委托的正确用法
  • 如何快速使用MCA Selector:Minecraft世界编辑完整指南
  • 基于springboot的摄影作品分享活动参与网站
  • Ostrakon-VL像素终端部署:离线环境无网络依赖运行方案
  • OCR数据集哪家强?ICDAR/CTW/Total-Text等8大主流数据集实战评测与下载指北
  • Untrunc终极指南:三步修复损坏MP4/MOV视频的完整教程
  • 【卷卷观察】Vibe Coding 时代:有些人已经在用 AI 写代码,有些人还在争论 AI 能不能写代码
  • Vibe Coding 完全实战手册:2026年 AI 辅助编程工作流从入门到精通
  • 基于springboot的新农村自建房改造管理系统
  • YOLO目标检测专用数据集:盲道识别与多类障碍物检测(16类别,9000张标注图)
  • 正则表达式 - 修饰符
  • SITS2026基准套件发布,立即获取首批28家头部实验室实测数据对比表,含GPT-5、Claude-4、Qwen-Max等6大模型得分详情
  • CLIP模型背后的秘密:为什么InfoNCE损失成为自监督学习的标配?