cen's blog cen's blog
首页
  • 编程文章

    • markdown使用
  • 学习笔记

    • 《JavaScript教程》
    • C++学习
    • C++数据结构
    • MySQL
    • Linux
  • 高中时代
  • 工作日常
  • CLion
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 分类
  • 标签
  • 归档
关于
GitHub (opens new window)

cen

十年饮冰,难凉热血
首页
  • 编程文章

    • markdown使用
  • 学习笔记

    • 《JavaScript教程》
    • C++学习
    • C++数据结构
    • MySQL
    • Linux
  • 高中时代
  • 工作日常
  • CLion
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 分类
  • 标签
  • 归档
关于
GitHub (opens new window)
  • 链表
  • 栈和队列
  • 二叉树
  • 堆
  • 排序
  • 搜索二叉树
  • 平衡二叉树
    • 引入
    • 插入数据
    • 旋转处理
      • 右单旋
      • 左单旋
      • 右左双旋
      • 左右双旋
    • 总结
  • 红黑树
  • 哈希表
  • C++数据结构
cen
2025-01-30
目录

平衡二叉树

# 引入

二叉搜索树虽然可以提高我们查找数据的效率,但如果插入二叉搜索树的数据是有序或接近有序的,此时二叉搜索树会退化为单支树,在单支树当中查找数据相当于在单链表当中查找数据,效率是很低下的。因此,引入了平衡二叉树。

AVL树可以是一棵具有以下性质的一棵二叉搜索树:

  • 树的左右子树都是AVL树
  • 树的左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)

# 插入数据

三个步骤:

  1. 按照搜索二叉树的插入方法,找到待插入位置
  2. 找到待插入位置后,将待插入结点插入到树中
  3. 更新平衡因子,如果出现不平衡,则需要进行必要的旋转
  • 插入数据:

若待插入结点的值小于根结点的值,则需要将结点插入到左子树当中 若待插入结点的值大于根结点的值,则需要将结点插入到右子树当中 若待插入结点的值等于根结点的值,则插入结点失败

  • 更新平衡因子:

插入一个结点后,该结点的祖先结点的平衡因子需要更新。

插入示意图

更新规则:

  • 新增结点在parent的右边,parent的平衡因子 ++
  • 新增结点在parent的左边,parent的平衡因子 −−

每更新完一个结点的平衡因子后,都需要进行以下判断:

  • 如果parent的平衡因子等于-1或者1,表明还需要继续往上更新平衡因子
  • 如果parent的平衡因子等于0,表明无需继续往上更新平衡因子了
  • 如果parent的平衡因子等于-2或者2,表明此时以parent结点为根结点的子树已经不平衡了,需要进行旋转处理

# 旋转处理

# 右单旋

当parent的平衡因子为2,cur的平衡因子为1时,进行右单旋

右旋

# 左单旋

当parent的平衡因子为-2,cur的平衡因子为-1时,进行左单旋

左旋

# 右左双旋

当parent的平衡因子为-2,cur的平衡因子为1时,进右左双旋

右左双旋

# 左右双旋

当parent的平衡因子为2,cur的平衡因子为-1时,进行左右双旋

左右双旋

# 总结

AVL树是一棵绝对平衡的二叉搜索树,其要求每个结点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度,即O(logn)。但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多。 因此,如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但当一个结构经常需要被修改时,AVL树就不太适合了。

上次更新: 2025/02/07, 18:31:39
搜索二叉树
红黑树

← 搜索二叉树 红黑树→

最近更新
01
线程安全
05-21
02
cmake教程
05-08
03
项目
05-07
更多文章>
Theme by Vdoing | Copyright © 2024-2025 京ICP备2020044002号-3 京公网安备11010502056119号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式