AVL树

AVL树是一种自平衡二叉搜索树,确保任意节点的两个子树高度差不超过1,从而保证操作效率在O(logn)。文章介绍了AVL树的概念、平衡因子、旋转操作(左旋、右旋)以及四种不平衡情况的调整策略,包括LL、RR、LR、RL。此外,还概述了AVL树的插入、删除和查找操作,并讨论了如何处理相同值的情况。
摘要由CSDN通过智能技术生成

AVL树

普通的二叉搜索树的退化

在使用二叉搜索树时,只规定了左子树的值小于根节点的值,右子树的值大于根节点的值,并没有对树的形状做出要求。

在树较为平衡(左右子树高度相差较小)时,如下图所示:
平衡时
我们在二叉搜索树上进行的增加、删除、查找的操作的时间复杂度平均为 O ( l o g   n ) O(log\,n) O(logn)

但是在树比较倾斜时,在二叉搜索树上的操作的时间复杂度也会随之增加,树越倾斜,退化也就越严重,时间复杂度也就越高。

一种极端情况下,当所有的节点(除叶节点外)都只有一个子树或子节点时,该树结构会退化为链表,相应的时间复杂度也会退化为 O ( n ) O(n) O(n)
不平衡时

为了解决这个问题,平衡树也就应运而生。其中最早的平衡树便是本文的重点——AVL树


什么是AVL树

AVL树是最早被发明的自平衡二叉搜索树。它的名字不是自平衡二叉搜索树的缩写,而是来源于它的发明者G. M. Adelson-VelskyEvgenii Landis

AVL树在二叉搜索树的性质上增加了一条——任一节点的两个子树高度差最大为1。因此,AVL树在执行增加、删除、查找操作的时间复杂度在平均、最坏情况下均为 O ( l o g   n ) O(log\,n) O(logn)。不会出现二叉搜索树中退化的情况。


平衡因子

AVL树中使用这个参数来判定当前节点是否是平衡的。平衡因子由当前节点的左子树高度减去右子树高度得到。

所以当一个节点的平衡因子大于1或小于-1时,则可以判定当前节点不平衡,需要进行调整。

另外,AVL树中也可以不保存节点的平衡因子,而保存树的高度,在需要时计算得到。


旋转

旋转是一种改变树的平衡性的操作,几乎所有的平衡树都是通过旋转操作来调整树的结构,使树保持平衡状态。

旋转分为两类:

  • 左旋转
  • 右旋转

左旋转

总共3步:

  • 将根节点的右子节点设置为右子节点的左子节点。
  • 将右子节点的左子节点设置为根节点。
  • 将右子节点设置为根节点。

相应的代码为:

AVLTreeNode* RotateL(AVLTreeNode* root) {
   
    AVLTreeNode* temp = root->right;
    root->right = temp->left;
    temp->left = root;

    return temp;
}

旋转前后对比:
左旋转

从图中可以看出,左旋转之后,相比于原来的树,左子树高度增加了1,右子树高度减少了1。

右旋转

类似于左旋转,也为三步:

  • 将根节点的左子节点设置为左子节点的右子节点。
  • 将左子节点的右子节点设置为根节点。
  • 将左子节点设置为根节点。

相应的代码为:

AVLTreeNode* RotateR(AVLTreeNode* root) {
   
    AVLTreeNode* temp = root->left;
    root->left = temp->right;
    temp->right = root;

    return temp;
}

旋转前后对比:
右旋转

从图中可以看出,右旋转之后,相比于原来的树,右子树高度增加了1,左子树高度减少了1。


AVL树中不平衡情况及对应旋转操作

在操作AVL树过程中,总共会遇到4种不平衡的情况:LLRRLRRL

LL情况——右旋转

LL情况是指根节点的子节点的子树高度比右子树高度大2的情况。即:
LL
图中A节点为根节点。

进行一次右旋转即可使树重新平衡。

RR情况——左旋转

RR情况是指根节点的子节点的子树高度比左子树高度大2的情况。即:
RR
图中A节点为根节点。

进行一次左旋转即可使树重新平衡。

LR情况——先左旋转,再右旋转

LR情况是指根节点的子节点的子树比左子树高度大2的情况。即:
LR
图中A节点为根节点。

此时需进行两次旋转:

  • 先以左子节点(B)为根进行一次左旋转。(将情况转化为LL情况)
  • 再以A节点为根进行一次右旋转

RL情况——先右旋转,再左旋转

RL情况是指根节点的子节点的子树比右子树高度大2的情况。即:
RL
图中A节点为根节点。

此时需进行两次旋转:

  • 先以右子节点(B)为根进行一次右旋转。(将情况转化为RR情况)
  • 再以A节点为根进行一次左旋转

AVL树的操作

在AVL树上操作主要有三种:增加删除查找

三种操作与二叉搜索树上对应的三种操作基本相同,只是增加、删除操作有可能会引起树的不平衡,需要进行额外调整。

为便于说明,此处先对AVL树结构进行说明:

class AVLTree {
   
  private:
    class AVLTreeNode {
   
      public:
        int val;              /// 当前节点所存的数值
        int height
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值