平衡二叉树
下面是每个模块的代码,AVL树创建的完整版代码以上传GitHub AVLTree的创建;
平衡二叉树(Balanced Binary Tree或Height-Balanced Tree)又称为AVL树。它或者是一颗空树,或者是具有下列性质的二叉树:
1、它的左子树和右子树都是平衡二叉树;
2、左子树和 右子树的深度之差的绝对值不超过1;
若将二叉树上结点的**平衡因子**BF定义为该节点的右子树的深度减去左子树的深度,则平衡二叉树和是哪个所有结点的平衡因子只可能是-1、0、1,只要二叉树上有一个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的;
我们希望有任何初始序列构成的二叉排序树都是AVL树。因为AVL树上任何结点的左右子树的深度之差都不超过1,则可以证明它的深度和logn是同数量级的(其中n为结点的个数),其实AVL树就可以防止搜二叉树的时间发咋读退化为O(n);
创建AVL树
因为,AVL树其实就是在二叉搜索树的基础上添加了一个表示平衡因子的元素来标记每个结点的平衡度。所以,我们可以在搜索二叉树的基础上来添加平衡因子更改为AVL树。如果对搜索二叉树不动的可以看搜索二叉树;
所以我们在构建搜索二叉树的时候,就应该对该结点的平衡因子做调整:
一般情况下,由于在二叉排序树上插入结点而失去了平衡可以归纳为4中情况:
(1)、单向右旋平衡处理
(2)、单向左旋平衡处理
(3)、双向旋转(先左后右)平衡处理
(4)、双向旋转(先右后左)平衡处理
在AVL树中插入结点P(key)结点算法:
步骤一:如果是空树,插入后即为根结点,插入后直接返回
步骤二:如果树不空,寻找插入位置,若在寻找的过程中找到key,则插入失败直接返回
步骤三:插入结点
步骤四:更新平衡因子,对树进行调整
新结点P的平衡因子PBF为0,但其双亲结点的平衡因子有三种情况:
1、结点PBF的平衡因子为0,每个结点的平衡因子不变,结束处理;
2、结点PBF的平衡因子为0,插入后PBF为根的子树没有失去平衡,但该字数的该子树的高度增1,需要查看PBF双亲的平衡因子;
3、结点PBF的平衡因子的绝对值为2;需要判断进行4中处理的那种平衡化处理;
图解###(图中的代码可能不是很正确,是在画图的时候写的,没有测试过,正确代码下面会给出)
左单旋
void _RotateL(Node* parent) //左单旋
{
Node* pSubR = parent->_pRight;
Node* pSubRL = pSubR->_pLeft;
parent->_pRight = pSubRL;
if (pSubRL)
pSubRL->_pParent = parent;
Node* PPparent = parent->_pParent;
pSubR->_pLeft = parent;
parent->_pParent = pSubR;
pSubR->_pParent = PPparent;
if (PPparent)
{
if (PPparent->_pLeft == parent)
PPparent->_pLeft = pSubR;
else
PPparent->_pRight = pSubR;
}
parent->_bf = pSubR->_bf = 0;
}
右单旋
void _RotateR(Node* parent)
{
Node* pSubL = parent->_pLeft;
Node* pSubLR = pSubL->_pRight;
parent->_pLeft = pSubLR;
if (pSubLR)
pSubLR->_pParent = parent;
Node* PPparent = parent->_pParent;
pSubL->_pRight = parent;
parent->_pParent = pSubL;
pSubL->_pParent = PPparent;
if (PPparent)
{
if (PPparent->_pLeft == parent)
PPparent->_pLeft = pSubL;
else
PPparent->_pRight = pSubL;
}
parent->_bf = pSubL->_bf = 0;
}
左右双旋
void _RotateLR(Node* parent)
{
Node* pSubL = parent->_pLeft;
Node* pSubLR = pSubL->_pRight;
int ret = pSubLR->_bf;
_RotateL(pSubL);
_RotateR(parent);
if (ret == -1)
parent->_bf = 1;
else if (ret == 1) // 这里要处理当他为0的时候的情况,平衡因子处理的特殊情况,最后一张图
pSubL->_bf = -1;
}
右左双旋
void _RotateRL(Node* parent)
{
Node* pSubR = parent->_pRight;
Node* pSubRL = pSubR->_pLeft;
int ret = pSubRL->_bf;
_RotateR(pSubR);
_RotateL(parent);
if (ret == -1)
pSubR->_bf = 1;
else if (ret == 1) // 平衡因子处理的特殊情况
parent->_bf = -1;
}
这张图就是在处理双旋时,他们平衡因子处理的特殊情况