AVL树详解(附c++代码)

本文详细介绍了AVL树的基本概念,包括其作为自平衡二叉搜索树的特性,以及如何通过左旋、右旋保持平衡。文章通过实例展示了节点平衡因子的计算,以及如何针对不同情况执行左旋、右旋操作来平衡树。同时,文章还讨论了AVL树的插入和删除操作,包括单子节点和双子节点删除的情况,强调了在这些操作后进行平衡的重要性。最后,作者提供了一段C++代码实现,尽管未在文章中展示,但指出代码可在Ubuntu环境下编译运行。
摘要由CSDN通过智能技术生成

1.AVL树简介

AVL树是一种自平衡的二叉搜索树,一颗典型的二叉搜索树(Binary Search Tree,以下简称BST)应该满足Key(left) < Key(root) < Key(right)。即左子树上所有的键值都小于根节点的键值,根节点的键值小于所有右子树上的键值(左右子树都不为空的话)。也正是因为这种特性,如果对于一般的BST不做任何平衡操作的话,在构建BST的时候左右子树的高度会出现严重不均衡的情况,例如:按照升序(降序)输入序列会造成最极端的不平衡情况。

                                

 

    图1  升序构建的BST                                                      图2 降序构建的BST                                                      图3  平衡的BST

 

1.1一些概念

为了解决这种情况,平衡的BST概念就应运而生了。其中AVL树是最先发明的自平衡二叉搜索树。自平衡的概念就是在插入、删除的过程中,树会自动平衡自身。在这里我们需要规定一下平衡的概念。一颗平衡二叉树,它的左右子树的高度差不能超过1,这个性质应用到这颗树的任意一个节点都要成立。树的高度的概念:从根节点出发,寻找到离它最远的叶节点所经过的路径,如果一个节点为空,它的高度为-1。高度的概念也可以应用到每一个节点。对于图1,节点1的高度为2,节点2的高度为1,节点3的高度为0.对于图3,节点1和节点3的高度都为0,节点2的高度为1。由此我们又可以引申出节点的平衡因子这个概念。一个节点的平衡因子是:height(x->left)-height(x->right),这里就不再举例细说了。

2.具体操作

2.1左旋、右旋、平衡

AVL树最重要的操作其实说穿了只有两个:左旋和右旋。我们所说的左旋右旋是针对某个节点而言。对于上文图1,将节点1向左旋转就形成了图3,对于图2 ,将节点3进行右旋就形成了图3。当某一个节点的平衡因子大于1时,要将该节点进行右旋;当某一节点的平衡因子小于-1时,要将该节点进行左旋。这里说法不够严谨,具体细节我们到平衡操作时再细说。平衡因子大于1,说明左子树高度至少比右子树高度大2,小于-1,右子树高度比左子树至少大2。具体旋转应该怎么操作呢,我们来看一个例子。

图4  左子树高的不平衡BST

 

 

 

 

         图5  右旋后平衡的BST

对比上面两幅图,我们发现不平衡发生在节点x,它的平衡因子为2,根据上文所说,那么从大方向上而言,它需要进行右旋。右旋过后如图5所示,我们发现,前后两颗树,只有被标记的三个节点的相对位置发生了变化,其他节点相对位置没有变化。用代码来表示就是

 

/*经由下面的3个步骤,原先x的左节点变为了新树的根节点,原先的x节点变为了新树左节点,原先x左节点的右节点变成了x节点的左孩子,还请好好理解*/
Node* t = x->left;       
x->left = t->right;
t->right = x;   

 

右旋操作就是这样,左旋操作很类似,我们以同样的方式来举例说明。

                                                            图6 右子树高的不平衡BST(图画的有点问题,x的balance=-2,x->right的balance=-1)


 

图7  左旋后平衡的BST

 

同样的,左旋时,相对位置发生变化的也只有被标记出来的3个节点。所以用代码来表示就是

 

Node* t = x->right;
x->right = t->left;
t->left = x;

和右旋的代码结构一模一样,只不过是对称了一下而已。

 

 

理解了左旋和右旋,那我们再来理解平衡就简单

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值