您的位置:首页 > 其它

AVL树(高度平衡的二叉搜索树)平衡因子的调节和旋转

2017-05-31 22:47 411 查看

1.什么叫AVL树?

                   AVL树又称为高度平衡的二叉搜索树,它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度(尽量使这棵树保持为完全二叉树,这样就能提高搜索效率)。


2.AVL树的性质

      (1)左子树和右子树的高度之差的绝对值不超过1

          (2) 树中的每个左子树和右子树都是AVL树  

          (3) 每个节点都有一个平衡因子(balance factor--bf),任一节点的平衡因子是-1,0,1。(每个节点的平衡因子等于右子树的高度减去左子  树的高度)

3.AVL树节点的定义
template <typename K,typename V>
struct AVLTreeNode
{
K _key;
V _value;
int _bf; //平衡因子,只能取值为-1,1,0
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
AVLTreeNode(const K& key, const V& value)
:_key(key)
, _value(value)
, _bf(0)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
{}
};


4.AVL树左单旋的情况






对应代码实现:

void _RotateL(Node* &parent)
{
//1.将要修改的结点标记起来
Node* SubR = parent->_right;
Node* SubRL = SubR->_left;
Node* pparent = parent->_parent;
//2.重新链上SubR结点
SubR->_left = parent;
SubR->_parent = pparent;
SubR->_bf = 0;
//4.重新链上parent结点
parent->_right = SubRL;
parent->_parent = SubR;
parent->_bf = 0;
//5.改变pparent的指向结点
if (pparent == NULL)
_root = SubR;
else if (pparent->_left == parent)
pparent->_left = SubR;
else
pparent->_right = SubR;
//4.重新链上SubRL结点
if (SubRL != NULL)
SubRL->_parent = parent;

}


5.AVL树右单旋的情况





对应的代码实现:

void _RotateR(Node* &parent)
{
//1.将要修改的结点标记起来
Node* SubL = parent->_left;
Node* SubLR = SubL->_right;
Node* pparent = parent->_parent;
//2.重新链上SubL结点
SubL->_right = parent;
SubL->_parent = parent->_parent;
SubL->_bf = 0;
//3.重新链上parent结点
parent->_left = SubLR;
parent->_parent = SubL;
parent->_bf = 0;
//4.改变pparent的指向结点
if (pparent == NULL)
_root = SubL;
else if (pparent->_left == parent)
pparent->_left = SubL;
else
pparent->_right = SubL;
//5.重新链上SubRL结点
if (SubLR != NULL)
SubLR->_parent = parent;
}


6.AVL树平衡因子的调节

     (1)插入的数据只能影响祖先结点的平衡因子;
    
     (2)当某个平衡因子从0变成1或者-1,需要继续调整祖先结点的平衡因子,直到根节点;
     
     (3)当某个平衡因子从-1或者1变成0,则不需要调整祖先的平衡因子了,因为平衡因子在插入数据之后变成0,证明整棵树的高度没有发生变化;



     (4)当平衡因子在插入数据之后变成-2或者2,需要通过旋转来降低它的高度,使它继续保持AVL树的性质

7.AVL树进行左右双旋的情况(注意平衡因子的调节)






代码实现:

void _RotateLR(Node* &parent)
{
//双旋的时候在某些情况下会导致bf发生异常
Node* SubL = parent->_left;
Node* SubLR = SubL->_right;
int bf = SubLR->_bf;
_RotateL(parent->_left);
_RotateR(parent);
if (bf == -1)
{
parent->_bf = 1;
SubL->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = 0;
SubL->_bf = -1;
}
else
{
SubL->_bf = parent->_bf = 0;
}
SubLR->_bf = 0;
}

8.同样的方法可以得到右左双旋时平衡因子的变化





                  (1)SubRL->_bf==0   parent->_bf=SubR->_bf=0;

  (2)SubRL->_bf==-1  parent->_bf=0  SubR->_bf=1;

  (3)SubRL->_bf==1   parent->_bf=-1 SubR->_bf=0;

代码实现:
void _RotateRL(Node* &parent)
{
Node* SubR = parent->_right;
Node* SubRL = SubR->_left;
int bf = SubRL->_bf;
_RotateR(parent->_right);
_RotateL(parent);
if (bf == 1)
{
parent->_bf = -1;
SubR->_bf = 0;
}
else if (bf == -1)
{
parent->_bf = 0;
SubR->_bf = 1;
}
else
{
SubR->_bf = parent->_bf = 0;
}
SubRL->_bf = 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息