news 2026/10/3 11:32:10

062AVL平衡二叉搜索树

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
062AVL平衡二叉搜索树

AVL平衡二叉搜索树 - 历史上第一个自平衡BST

062AVL树:一场平衡之舞

📰 5W1H 发明者故事

Who(何人)- 发明者是谁?

发明者:格奥尔基·阿杰尔松-韦利斯基(Georgy Adelson-Velsky,1922-2014)和叶夫根尼·兰迪斯(Evgenii Landis,1921-1997)
背景:

  • Adelson-Velsky:苏联数学家,莫斯科国立大学教授,后移民以色列,在以色列理工学院工作;他还参与了世界上第一个计算机国际象棋程序Kaissa的开发
  • Landis:苏联数学家,以微分方程研究闻名,与Adelson-Velsky合作研究数据结构的数学性质
  • 两人均是应用数学家而非纯粹的计算机科学家,这也解释了AVL树严格数学分析的风格

When(何时)- 什么时候发明的?

时间:1962年,论文"An Algorithm for the Organization of Information"发表于苏联科学院院刊(Doklady Akademii Nauk SSSR)
时代背景:

  • 刚好在Hibbard(1962)发表BST删除算法的同一年
  • 冷战时期,苏联和西方计算机科学研究相互隔绝,AVL树在西方被重新发现时已是1970年代
  • 苏联在这一时期有世界级的数学和计算机科学研究,但成果传播受政治限制

Where(何地)- 在哪里发明的?

地点:苏联,莫斯科国立大学(Московский государственный университет)
环境:

  • 冷战高峰期,苏联政府大力资助基础科学研究
  • 莫斯科大学数学系是世界顶级研究机构,聚集了大批优秀数学家
  • 论文以俄语发表,后被翻译为英语,使西方学者在数年后才了解这一成果

What(何事)- 发明了什么?

数据结构:AVL树(以两位发明者姓名首字母命名:Adelson-Velsky and Landis)
核心性质(AVL条件):对树中每一个节点,其左子树和右子树的高度差(平衡因子)不超过1
关键突破:

  • 首次证明:维护平衡因子为{-1,0,1}的BST,树高度始终保持在 1.44 log₂N 以内
  • 定义了四种旋转操作(LL/RR/LR/RL)来恢复平衡,且每次旋转只需O(1)时间
  • 证明任意插入/删除操作后,至多需要 O(log N) 次旋转即可恢复平衡

四种旋转类型:

LL旋转(右旋): RR旋转(左旋): LR旋转(先左后右): RL旋转(先右后左): z z z z / \ / \ / \ / \ y T4 T1 y y T4 T1 y / \ / \ / \ / \ x T3 T2 x T1 x x T4 / \ T2 T3

Why(何因)- 为什么发明?

要解决的问题:

  1. 普通BST在最坏情况下(如顺序插入)退化为链表,查找退化为O(N)
  2. 需要一个保证最坏情况O(log N)的动态查找结构,而非平均情况保证
  3. 随机化方案(如跳表)引入概率,不能保证严格的最坏情况

理论依据:

  • AVL条件保证树高度 h <= 1.44 log₂(N+2) - 0.328
  • 这意味着所有操作(查找、插入、删除)的最坏情况均为O(log N)
  • 相比BST的O(N)最坏情况,这是质的飞跃

当时的挑战:

  • 平衡维护的正确性需要严格的数学证明(苏联数学家的强项)
  • 四种旋转情况的分类和实现容易出错
  • 删除操作比插入更复杂(可能需要从删除点到根的全路径旋转)

How(何果)- 如何实现?有什么影响?

插入流程:

1. 按BST规则插入新节点 2. 从新节点向上回溯到根,更新每个祖先的平衡因子 3. 找到第一个失衡节点(平衡因子变为±2) 4. 根据失衡类型执行对应旋转(LL/RR/LR/RL) 5. 旋转后该子树高度恢复,停止回溯

历史影响:

  • AVL树开创了"自平衡搜索树"这一重要研究方向
  • 直接启发了红黑树(1972年,Rudolf Bayer)、B树(1970年)等后续结构
  • 红黑树(std::set/std::map的基础)是AVL树的工程优化版本(旋转次数更少)
  • Java的TreeMap、C++ STL的set/map都基于红黑树(AVL树的精神继承者)

今天的使用:

  • 数据库内存索引(某些实现用AVL树,因其查找比红黑树更快)
  • 实时系统(AVL树高度更严格,查找更稳定)
  • 操作系统内核(OpenBSD内核的某些数据结构使用AVL树)

名言:Knuth在TAOCP中写道:“AVL树是平衡搜索树中最优雅的结构,它以最少的约束(平衡因子至多为1)换取了最强的保证(高度至多为1.44logN)。”


📝 自然语言需求定义

需求名称:实现AVL树,支持插入和查找,保证任意时刻高度 ≤ 1.44 log₂N

功能需求(用精确的中文描述)

  1. 插入(含平衡维护):向AVL树插入值,插入后自动通过旋转恢复平衡

    • 输入:根节点指针的指针、整数值
    • 操作:BST插入 → 向上回溯更新高度 → 检测失衡 → 执行旋转(LL/RR/LR/RL)
    • 输出:无(就地修改,返回新根)
  2. 查找:在AVL树中查找值(与BST查找相同,利用BST性质)

    • 输入:根节点指针、目标值
    • 输出:找到返回节点指针,未找到返回NULL
  3. 四种旋转操作(内部函数):

    • 右旋(LL情况):将左孩子提升为新根
    • 左旋(RR情况):将右孩子提升为新根
    • 左右旋(LR情况):先对左孩子左旋,再对当前节点右旋
    • 右左旋(RL情况):先对右孩子右旋,再对当前节点左旋
  4. 高度查询:返回AVL树高度(空树为-1)

  5. 中序遍历:按升序遍历(与BST相同,用于验证有序性)

  6. 释放内存:后序遍历释放所有节点

约束条件

  • 每个节点维护height字段(而非balance_factor,以简化实现)
  • 平衡因子 = 左子树高度 - 右子树高度,|平衡因子| <= 1
  • 不实现删除(删除更复杂,单独成一个高级话题)
  • 重复值忽略
  • 10个节点插入后树高度必须 <= 4(1.44 × log₂(10) ≈ 4.78,实际AVL树会更低)

验收标准(必须可验证)

编号测试场景(自然语言描述)预期结果验证方式
1顺序插入1,2,3(会触发RR旋转)树高度=1,根为2断言height(root)<=1
2插入3,2,1(触发LL旋转)树高度=1,根为2断言height和root->data
3插入3,1,2(触发LR旋转)树高度=1,根为2断言height和root->data
4插入3,5,4(触发RL旋转)树高度=1,根为4断言height和root->data
5插入10个元素后树高度高度 <= 4断言height(root) <= 4
6插入后中序遍历有序中序遍历结果严格递增断言数组各相邻元素
7查找存在的值返回非NULL节点断言
8查找不存在的值返回NULL断言
9顺序插入1到20,高度 <= 1.44*log2(20)+1高度 <= 6断言

AI 生成提示

基于以上需求和验收标准,用标准C语言实现AVL树(含四种旋转,不实现删除)。 要求: 1. 使用标准C99,gcc -Wall无警告 2. 节点结构体:int data, int height, AVLNode* left, AVLNode* right 3. 高度维护:每次插入后递归更新height字段 4. 实现四种旋转:rotate_right, rotate_left, rotate_left_right, rotate_right_left 5. avl_insert返回新根指针 6. 完整测试框架:tests_passed/tests_failed计数 7. main最后返回 tests_failed > 0 ? 1 : 0 核心函数: - avl_insert(root, value) - 递归插入,返回新根指针 - avl_search(root, value) - 查找,返回节点指针 - avl_height(root) - 树高度(空树-1) - avl_inorder(root, arr, &cnt) - 中序遍历 - avl_free(root) - 释放内存 - rotate_right(y) / rotate_left(x) - 基本旋转

💻 C语言实现文件

对应文件:avl_tree.c

编译运行:

gcc-std=c99-Wall-oavl_tree_test avl_tree.c ./avl_tree_test# 内存泄漏检测valgrind --leak-check=full ./avl_tree_test

核心函数:

  • avl_insert(root, value)- 递归插入并自动旋转,返回新根
  • avl_search(root, value)- 查找,返回节点指针或NULL
  • avl_height(root)- 返回树高度(空树返回-1)
  • avl_inorder(root, arr, &cnt)- 中序遍历填数组
  • avl_free(root)- 后序遍历释放所有节点
  • rotate_right(y)/rotate_left(x)- LL/RR基本旋转
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 11:31:59

国产DCS突破关键:从MTBF 12万小时到SIL2认证落地

1. 从“能用”到“敢用”&#xff1a;DCS国产化突破的真实分水岭在哪&#xff1f;“国产巨头DCS第一之后&#xff0c;全球工控玩家们坐不住了&#xff01;”——这句话最近在自动化圈子里传得很快&#xff0c;但很多人点开新闻只看到一句“市场份额登顶”&#xff0c;就匆匆划走…

作者头像 李华
网站建设 2026/10/3 11:29:46

Oracle 11g升级19c完全指南:RMAN备份、catctl执行与避坑手册

简介&#xff1a;面向Oracle数据库运维人员的一份升级实战手册&#xff0c;核心讲解如何利用DBUA工具&#xff0c;将Oracle 11g生产库平稳升级至19C。内容从升级前的环境评估开始&#xff0c;覆盖备份恢复、参数文件与归档日志处理、源库与目标库目录规划、DBUA执行及升级后配置…

作者头像 李华
网站建设 2026/10/3 11:29:13

英飞凌TC3XX CAN开发实战:MultiCAN+模块配置与错误帧排查

做车载和工业控制这些年&#xff0c;英飞凌TC3XX的MultiCAN模块是我见过配置项最多、也最容易被低估的CAN控制器。很多人从STM32转到AURIX平台后&#xff0c;第一感觉是“不就配个波特率嘛”&#xff0c;结果被Message Object分配、节点与MO映射、FIFO缓冲、CAN FD双波特率这些…

作者头像 李华
网站建设 2026/10/3 11:26:02

海上风电智慧运维实战:EHS标准化与TCM振动监测降本策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/3 11:25:38

Redis Hash底层编码揭秘:ziplist、listpack与hashtable如何选

很多人在业务里第一次用 Redis 存对象&#xff0c;第一反应就是 string&#xff1a;对象转成 JSON&#xff0c;塞进去&#xff0c;完事。直到后来要改其中一个字段&#xff0c;才发现每次都要先 get、再反序列化、改完再序列化、最后 set&#xff0c;既麻烦又容易踩并发覆盖的坑…

作者头像 李华
网站建设 2026/10/3 11:24:20

本地知识助手:用RAG打通Wiki与代码仓库,解决文档漂移困扰

你有没有过这种体验&#xff1a;翻了大半天的团队 Wiki&#xff0c;好不容易找到一篇接口文档&#xff0c;对着代码一看&#xff0c;页面里写的参数名早改了三个版本。反过来&#xff0c;代码里明明用注释和命名讲清楚了核心业务逻辑&#xff0c;但你在 Wiki 里搜破头都搜不到—…

作者头像 李华