https://blog.csdn.net/fengyuyeguirenenen/article/details/123175641
符号说明
当前结点: pr
平衡因子: bf
当前结点子节点: p
画图工具: avl树
一.平衡因子
平衡因子bf = 左子树高 - 右子树高
bf数值 | 正值 | 0 | 负值 |
---|---|---|---|
形状 | 左倾斜 | 完全平衡 | 右倾斜 |
二.非平衡状态
根据pr和p的bf判断非平衡状态树形
右边是pr(当前结点)的bf 下边是p(子结点)的bf | +2 | -2 |
---|---|---|
+1 | LL型 | RL型 |
0 | LL型 | RL型 |
-1 | LR型 | RR型 |
(1).LL型(pr左倾,p左倾或完全平衡,非平衡状态)
(2).RR型(pr右倾,p右倾或完全平衡,非平衡状态)
(3).LR型(pr左倾,p右倾非平衡状态)
(4).RL型(pr右倾,p左倾非平衡状态)
三.平衡调整(旋转)
非平衡状态 | |
---|---|
LL型 | pr右旋 |
RR型 | pr左旋 |
LR型 | p先左旋,使树形变为LL型,pr再右旋 |
RL型 | p先右旋,使树形变为RR型,pr再左旋 |
1.LL型 -> 右旋: 结点移到左孩子的右结点
2.RR型 -> 左旋: 结点移到右孩子的左结点
3.LR型 -> p先左旋,使树形变为LL型,pr再右旋
4.RL型 -> p先右旋,使树形变为RR型,pr再左旋
四.结点插入
1. 查找要插入的位置并插入结点
从根结点开始,与树中结点进行比较,查找要插入的位置。
如果小于则向左走,如果大于则向右走,把这个过程中的每一个结点都放入一个栈中
,这样直到到达叶子结点,即找到了插入的位置并插入结点。
2. 插入完成以后进行平衡调整
取出查找时记录栈中的结点调整平衡因子:插入的结点对于取出的结点如果是左边插入,则平衡因子减1,如果右边插入则平衡因子加1.
结点调整后bf | 分析 |
---|---|
0 | 插入节点前平衡因子只能是正负1,现在结点完全平衡,因此并不改变该子树的高度。所以树是平衡的,不需要调整,调整结束。 |
+1或-1 | 因为在此之前该结点的平衡因子只能是0,变为正负1意味着该结点所在的子树高度发生变化。所以继续取出栈下一个结点进行检查 。 |
+2或-2 | 该结点处于非平衡状态,按照pr和p的bf判断出非平衡状态的树形并进行相应的旋转调整,使该子树平衡。 由于调整之后树高就减少一层,抵消了插入节点带来的树高增加一层的变化, 所以树是平衡的,不需要调整,调整结束。 |
五.结点删除
1.查找要删除的结点
从根结点开始,与树中结点进行比较。
如果小于则向左走,如果大于则向右走,把这个过程中的每一个结点都放入一个栈中
,直到找到要删除的结点。
2.删除结点
要删除的结点,分为三种情况
-
删除结点为叶子结点,则直接删除
-
删除结点只有一个孩子结点,则删除该结点,并将仅有的一个孩子节点提上来即可。
-
删除结点左右两个孩子都存在,直接删除不方便,则与右子树中的最左子结点交换。
因为右子树的最左节点是比删除结点大的值最接近的结点,交换不影响树中元素排序,交换后将问题转为删除右子树中的最左子结点。
而且右子树的最左节点要么是叶子结点,则可以按照1中叶子结点来删除。要么没有左孩子,只有一个右孩子,则按照2中只有一个孩子结点来删除。
3. 删除完成以后进行平衡调整
取出查找时记录的栈中结点调整平衡因子,如果删除结点比该结点的值小,则必定是左边删除,则平衡因子减1否则加1.
结点调整后bf | 分析 |
---|---|
0 | 删除之前平衡因子是+1或-1,删除结点以后变为0,子树的高度减1。则要向上继续取出栈下一个结点进行检查 |
+1或-1 | 删除节点之前,该结点bf是0,即左右平衡,删除以后左树或右树少了一个结点,但该结点子树高度并没发生变化。所以树是平衡的,不需要调整,调整结束。 |
+2或-2 | 该结点处于非平衡状态,按照pr和p的bf判断出非平衡状态的树形并进行相应的旋转调整,使该子树平衡。 因为调整的时候有可能会使该结点子树高减少一层,所以需要继续向上检查. |