数据结构与算法(十四)平衡二叉树(AVL树)

本文介绍了平衡二叉树(AVL树)的概念,解释了什么是高度平衡和平衡因子,并详细阐述了其插入和删除操作,包括左旋、右旋以及平衡算法。通过对数组的插入演示,展示了如何构建和调整平衡二叉树,以保持高效查找、插入和删除性能。
摘要由CSDN通过智能技术生成

二叉排序树在使用时可能会出现极端的左或右斜树的现象,导致算法效率大大降低,这称为二叉排序树的不平衡。

而我们在使用的时候,总是希望二叉排序树是平衡的,使算法的效率最大化,所以就有了平衡二叉树(AVL树)。

1、平衡二叉树(AVL树)

从平衡二叉树的英文名字,你也可以体会到,它是一种高度平衡的二叉排序树,那什么叫做高度平衡呢?意思是说,要么它是一棵空树,要么它的左子树和右子树都是平衡二叉树, 并且左子树和右子树的深度之差的绝对值不超过 1。

我们将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子 BF (Balance Factor) ,那么平衡二叉树上所有结点的平衡因子只可能是1、0或-1,只要二叉树上某个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。

很显然之前文章构造的二叉排序树都是不平衡的,左图的二叉排序树的58结点的左子树深度为3,右子树深度为0,就更不用说右图的右斜树了。

我们可以通过适当的调整使左图的二叉排序树变成平衡二叉树,如下图。

以距离插入结点最近的,且平衡因子的绝对值大于1的结点为根的子树,称为最小不平衡子树。

1.1、平衡二叉树(AVL树)的实现原理

平衡二叉树构建的基本思想就是在构建二叉排序树的过程中,每插入一个结点时,先检查是否因插入而破坏树的平衡性,若是,则找出最小不平衡子树。在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。

假设我们需要对数组 a[10]={3, 2, 1, 4, 5, 6, 7, 10, 9, 8}来构建一颗二叉排序树,如果没有学习平衡二叉树,那么根据二叉排序树的性质,我们通常会构建成如下图图1的二叉排序树,虽然它完全符合二叉排序树的定义,但是这样高度达到8的二叉树对于查找、插入和删除的效率来说是非常不利的,而我们更期望能构建成如下图图2的平衡二叉树,高度为4的二叉排序树才可以提供高效的查找、插入和删除效率。

如何构建一颗平衡二叉树呢?

首先给出平衡二叉树的结构,就是一般的二叉树:

typedef int DataType;    /*树结点的数据元素类型*/
typedef struct BinaryNode {   /*二叉树结点结构*/
    DataType data;            /*数据域*/
    BinaryNode *leftChild;    /*左孩子*/ 
    BinaryNode *rightChild;   /*右孩子*/
}*BinaryTree;

然后根据平衡因子BF的性质,实现二叉树结点BF值算法:

/*二叉树结点BF值算法*/
int BinaryTreeBF(BinaryTree left, BinaryTree right)
{
    int leftChildDepth = BinaryTreeDepth(left);   /*得出左子树深度*/ 
    int rightChildDepth = BinaryTreeDepth(right); /*得出右子树深度*/
    return (leftChildDepth-rightChildDepth);      /*BF=左子树深度-右子树深度*/
}

附录:二叉树深度递归算法

/*二叉树深度递归算法*/
int BinaryTreeDepth(BinaryTree T)
{
    if (T == NULL) return 0; /*不存在,所以返回深度为0*/	
    int leftChildDepth, rightChildDepth, maxDepth;
    leftChildDepth  = BinaryTreeDepth(T->leftChild);  /*递归左子树的深度*/
    rightChildDepth = BinaryTreeDepth(T->rightChild); /*递归右子树的深度*/
    /*在左子树的深度和右子树的深度中选取最大的,并把这一层的深度加上*/
    maxDepth = (leftChildDepth > rightChildDepth) ? (leftChildDepth+1) : (rightChildDepth+1); 
    return maxDepth;/*返回最大深度*/
}

对于[10]={3, 2, 1, 4, 5, 6, 7, 10, 9, 8}的前两个数3和2,我们正常的构建二叉排序树,但是插入第三个数1时,发现根结点3的BF值为2了,此时整棵树为最小不平衡子树,因此需要调整。

当最小不平衡子树的根结点的BF值为正数时,我们将整个最小不平衡子树进行右旋处理,反之BF值为负数进行左旋处理。

右旋处理后,结点2成为了根结点,结点3成为根结点2的右孩子,此时三个结点的BF值都为0,整颗二叉排序树非常的平衡。

然后我们再插入第四个数4 ,没有结点的BF值超过限定范围。

当我们插入第五个数5时,结点3的BF值为-2,说明需要进行左旋处理,处理后整颗树又达到了平衡。

此时需要解释平衡二叉树的左旋和右旋处理的具体操作:

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值