平衡二叉树(AVL)的创建、插入、删除

AVL树是一种平衡二叉排序树,能有效提高查找效率。在插入或删除节点后可能需要重新平衡。文章详细阐述了AVL树的创建、插入和删除过程,包括插入和删除时的不平衡节点调整策略,如LL型、LR型等,并提供了关键源代码参考。
摘要由CSDN通过智能技术生成

一、概念

 平衡二叉树(下文称AVL)是满足每个结点的左右子树高度(亦称深度)之差在{0,1,-1}这个范围内的二叉排序树(二叉排序树也叫二叉搜索树)。

AVL的优势是在查找时避免了出现一般二叉排序树查找的最坏情况。但是AVL在经过插入或删除结点的操作之后可能出现不平衡的情况,所以每次插入或删除完之后要判断是否平衡,不平衡就需要rebalance.这会增加插入删除的复杂度。

二、AVL的创建

正常的有规律的创建方法(实际上是各种资料采用的方法)是将创建,
看成从NULL开始,一次次对原有的AVL的插入(显然只有一个结点的Tree一定是AVL)。

三、AVL的插入
1.方法:

先把结点按二叉排序树的结构正常插入,再由底向上逐级判断是否平衡,不平衡就rebalance. 插一次可能经过几次rebalance。(具体情况请往下读)

2.插入处的叶子节点的情况:
这里写图片描述

                                 图1

显然

  1) 插入处的叶子有且仅有这4种情况
  2)对于②④来说,一定不影响原有树平衡
  3)对于①③来说,不确定是否影响原有树的平衡;如果影响,不平衡点一定在结点A的祖先结点中(包括父亲节点,下文同)。
  4)对于①③来说,我们要把这种不平衡的可能逐级传递给A的祖先结点,再逐级判断A的祖先节点 a.是否不平衡,不平衡需要rebalance, 
    之后b.是否有影响上一级平衡性的可能,有就需要继续传递这种可能。进行递归

3.不平衡节点的情况

!!注意:这里讨论的是三、2.4)中逐级往上,第一个出现不平衡的节点的情况。其他节点若不平衡都是依次逐级递归调整,讨论且只有讨论第一个出现的不平衡的节点的情况才有意义。

(1)插入前
这里写图片描述

                               图2
注:
LH:左子树高  
RH:右子树高 
EQ:左右子树等高
x:深度值

显然,

1)插入后第一个出现不平衡的节点在插入前有且仅有这两种情况
2)我们只需讨论其中一种情况,另一种同理可解

本文选择第一种,下文即根据第一种而展开

(2)插入后
这里写图片描述

                              图3
注:
DISEQ_LH:因为左子树过高而不平衡
DISEQ_RH:因为右子树过高而不平衡

显然

1)第一个出现不平衡的节点有且仅有这两种情况
2)有的书籍中将第一种情况称为”LL型“,第二种情况称为"LR"型

(3)对于”LL型“的讨论
这里写图片描述

                              图4

显然,

1)LL型有且仅有这两种情况
2)有的书籍将第一种情况称为"LL的一般型”,第二种称为“LL的简单型”,这很明显是不科学的,甚至是错误的叫法,
  因为一般型不能包含简单型还叫一般吗?本文将第一种称为”LL的次简型“,第二种称为“LL的最简型”。
3)rebalance方法如下图(二者代码一致):

这里写图片描述

                             图5

(3)对于”LR型“的讨论
这里写图片描述

                           图6

显然

1)"LR型"有且仅有这两种情况
2)本文将第一种称为”LR的次简型“,第二种称为“LR的最简型”
3)rebalance方法如下图(二者代码不一致,主要在于平衡因子的改变不同):

这里写图片描述

                           图7

四、AVL的删除
1.方法:

1)删除:先找到要删除的结点;然后判断结点的子树情况,如果无子树,直接删除,如果有一个孩子,删除后将孩子结点接到父亲结点上,
 如果有两个孩子,可以选择a.在左孩子中找到最大结点 b.在右孩子中找到最小结点 ,将找到的节点与要删除的结点的data替换,
 然后问题转化为在删除结点的左子树中删除找到的结点。变成递归。
2)出现不平衡,即进行rebalance,删除一次可能rebalance多次

2.删除处的叶子节点的情况
!!注意,此处指的是四、1.1)中递归到最后删除叶子结点的情况
这里写图片描述

                           图8

显然,

1)删除处的叶子有且仅有这4种情况
2)对于②④来说,一定不影响原有树平衡
3)对于①③来说,不确定是否影响原有树的平衡;如果影响,不平衡点一定在结点A的祖先结点中(包括父亲节点,下文同)。
 a.是否不平衡,不平衡需要rebalance, 之后b.是否有影响上一级平衡性的可能,有就需要继续传递这种可能。进行递归。

3.不平衡节点的情况
!!注意:这里讨论的是三、2.4)中逐级往上,第一个出现不平衡的节点的情况。其他节点若不平衡都是依次逐级递归调整,讨论且只有讨论第一个出现的不平衡的节点的情况才有意义。
(1)删除前
这里写图片描述

                                 图9

显然,
1)删除后第一个出现不平衡的节点在插入前有且仅有这两种情况
2)我们只需讨论其中一种情况,另一种同理可解(本文选择第一种,下文即针对第一种情况而展开

(2)删除后
这里写图片描述

                             图10

显然,

1)第一个出现不平衡的节点有且仅有这3种情况
2)对照前面的插入操作,我们知道,第一种不平衡情况称为”LL型“,第二种情况称为"LR"型,那么第三种呢?有的教材将其归为前两种之一,
那明显是错误的,请那么做的作者去看LL、LR型的定义。有的教材更差劲,甚至不讲AVL删除操作。我将第三种情况命名为“LE型”。

(3)对于”LL型“的讨论

操作同插入时的“LL型”,但请清楚具体情况与插入时不同

(4)对于”LR型“的讨论
这里写图片描述

                           图11

(5)对于”LE型“的讨论
这里写图片描述

                           图12
注:对于”LE型“,可以用"LL型"的操作旋转节点,也可以用"LR型“的操作旋转节点。(但注意过后平衡因子的改变与LL或LR不同),应用LL显然更简单。

五、关键源代码

enum BalanceFactor //平衡因子取值
    { 
        DISEQ_RH = -2, //因为右子树高2不平衡
        RH = -1, //右子树比左子树高1
        EQ = 0,  //左右子树等高
        LH =1,   //左子树比右子树高1
        DISEQ_LH = 2 //因为左子树高2不平衡
};

typedef struct Tnode
{
     BalanceFactor t_balancefacor;
     float t_data;
     struct  Tnode* lchild;
     struct  Tnode* rchild;
}Tnode;

void createBBST(Tnode* &tree);
bool searchBBST(Tnode* tree, float search_data);
bool insertBBST(Tnode* &tree, float insert_data, bool &taller);
bool deleteBBST(Tnode* &tree, float delete_data, bool &shorter);
/*注意:AVL的插入和删除是有固定方法的,虽然还有其他手段也能使得插入后的AV
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值