插入
若向平衡二叉树中 插入一个新结点后破坏了平衡二叉树的平衡性。首先要找出插入新结点后失去平衡的根结点的指针 最小子树 。然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。当失去平衡的最小子树被调整为平衡子树后, 原有其他所有不平衡子树无需调整 ,整个二叉排序树就又成为一棵平衡二叉树。失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于 1 的结点作为根的子树。假设用 A 表示失去平衡的最小子树的根结点,则调整该子树的操作可归纳为下列四种情况。
插入方式:跟查找二叉树一样的方式插入一个新的节点。(一直找到叶子处,新节点挂在旧叶子下)
平衡查找:构造完新的查找树之后,比较过的节点为根的子树都要验证是不是还平衡,如果不平衡的话,需要平衡化。
平衡校验:增加一个节点的高度,heigh = (max(leftHeigh) > max(rightHeight)?max(leftHeigh) :max(rightHeight))+1,
校验是不是超过1了。
平衡化方式:旋转,方式如下:
( 1 ) RR 型平衡旋转法
由于在 A 的左孩子 B 的左子树上插入结点 F ,使 A 的平衡因子由 1 增至 2 而失去平衡。故需进行一次顺时针旋转操作。 即将 A 的左孩子 B 向右上旋转代替 A 作为根结点, A 向右下旋转成为 B 的右子树的根结点。而原来 B 的右子树则变成 A 的左子树。
( 2 ) LL 型平衡旋转法
由于在 A 的右孩子 C 的右子树上插入结点 F ,使 A 的平衡因子由 -1 减至 -2 而失去平衡。故需进行一次逆时针旋转操作。即将 A的右孩子 C 向左上旋转代替 A 作为根结点, A 向左下旋转成为 C 的左子树的根结点。而原来 C 的左子树则变成 A 的右子树。
( 3 ) LR 型平衡旋转法
由于在 A 的左孩子 B 的右子数上插入结点 F ,使 A 的平衡因子由 1 增至 2 而失去平衡。故需进行两次旋转操作(先逆时针,后顺时针)。即先将 A 结点的左孩子 B 的右子树的根结点 D 向左上旋转提升到 B 结点的位置,然后再把该 D 结点向右上旋转提升到 A 结点的位置。即先使之成为 LL 型,再按 LL 型处理 。
如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到 A 的左子树上,此时成为 LL 型,再按 LL 型处理成平衡型。
( 4 ) RL 型平衡旋转法
由于在 A 的右孩子 C 的左子树上插入结点 F ,使 A 的平衡因子由 -1 减至 -2 而失去平衡。故需进行两次旋转操作(先顺时针,后逆时针),即先将 A 结点的右孩子 C 的左子树的根结点 D 向右上旋转提升到 C 结点的位置,然后再把该 D 结点向左上旋转提升到 A 结点的位置。即先使之成为 RR 型,再按 RR 型处理。
如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到 A 的左子树上,此时成为 RR 型,再按 RR 型处理成平衡型。
平衡化靠的是旋转。 参与旋转的是 3 个节点(其中一个可能是外部节点 NULL ),旋转就是把这 3 个节点转个位置。注意的是,左旋的时候 p->right 一定不为空,右旋的时候 p->left 一定不为空,这是显而易见的。
如果从空树开始建立,并时刻保持平衡,那么不平衡只会发生在插入删除操作上,而不平衡的标志就是出现 bf == 2 或者 bf == -2的节点。
删除
在删除的时候,同样会导致平衡二叉树失衡。
1.删除方式:先查找到对应的节点,删除
2.树的连续性保证:跟查找树一样的方式
2.1.如果被删除的子树只有一个节点,那么把该节点替换删除的节点
2.2.如果就是一个叶子,直接删除
2.3.删除节点又有左节点,又有右子树。那么要么找出右子树的最小节点或者找出左子树的最大节点替换被删除的节点。
2.4.删除之后,同样要检查是不是保持平衡。
平衡二叉树的插入和删除的代码实现
AvlTree.h
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 #pragma once 5 6 //平衡二叉树结点 7 template <typename T> 8 struct AvlNode 9 { 10 T data; 11 int height; //结点所在高度,校验平衡度 12 AvlNode<T> *left; 13 AvlNode<T> *right; 14 AvlNode<T>(const T theData) : data(theData), left(NULL), right(NULL), height(0){} 15 }; 16 17 //AvlTree 18 template <typename T> 19 class AvlTree 20 { 21 public: 22 Av