AVL树

                                                                                                   数据结构——AVL

1、为什么要引入AVL

在前面的一节引入了二叉搜索树,这样可以方便搜索,但搜索的效率取决于搜索树的高度;因此要想提高查询的效率,便要降低二叉搜索树的高度。

2、什么是AVL树?

AVL树又称为高度平衡的二叉搜索树,是1962年有俄罗斯的数学家G.M.Adel'son-Vel'skii和E.M.Landis提出来的。(AVL的由来)它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度。

3、AVL树的性质

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

既然它是平衡树,那么它的高度差,为什么是不超过1而不是等于0?

因为当为偶数个结点时,它的的高度差不可能等于0;即不能达到完全平衡

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

3.3) 每个节点都有一个平衡因子(balance factor--bf),任一节点的平衡因子是-1,0,1。(每个节点的平衡因子等于右子树的高度减去左子树的高度 )注意:平衡因子也可以用高度来替换;

4、AVL树的实现

 4.1AVL树的插入


     AVL树中插入一个结点,需考虑一下问题

     1、插入这个结点后,树的高度有变化,则需看它对祖先结点有无影响(即看祖先结点的平衡因子的值)

   2、判断是否需要调平衡(平衡因子为2时);

   3、判断旋转方式;单旋、双旋

  区分:左单旋与右左双旋 

右旋与左右双旋的区分与上图类似;

插入的代码实现:

      bool Insert(const K& key, const V& value=V())
{
if(_root == NULL)
{
_root = new Node(key,value);
return true;
}
Node* cur = _root;
Node* parent = NULL;
while(cur)
{
if(cur->_key > key)
{
               parent = cur;
  cur = cur->_left;
}
else if(cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else
return false;
}
 cur=new Node(key,value);
      if(parent->_key > key)
 {
          parent->_left = cur;
     cur->_parent=parent; 
 }
 else
 {
 parent->_right = cur;
     cur->_parent=parent;    
 }
while(parent)//调平衡因子
{
if(parent->_left == cur )
parent->_bf -- ;
else 
parent->_bf ++ ;
 


if(parent->_bf == 0)//高度没变
break;
else if(parent->_bf == 1 || parent->_bf == -1)//逐级调平衡
{
            cur = parent ;
parent = cur->_parent ;
}
else if(parent->_bf == 2 || parent->_bf == -2)//旋转
{
if(parent->_bf == 2)//左旋
{
    Node* subR = parent ->_right ;


if(subR->_bf == 1)//左单旋
{
                     RotateL(parent);
return true;


}
else if(subR->_bf == -1)//右左双旋
{
                     RotateRL(parent);
return true;
}


}
 
else
{
Node* subL= parent->_left ;
if(subL->_bf == -1)//右单旋
{
                     RotateR(parent);
return true;
}
else if(subL->_bf == 1)//左右双旋
{
                     RotateLR(parent);
return true;
}


}
}
else
assert(false);//平衡因子出错
      }
  return false;
}


5、AVL树的调平衡

左旋:

右左双旋:

右旋:

左右双旋:

6、AVL树整体代码实现

#include
    
    
     
     
#include
     
     
      
      
using namespace std ;
template
      
      
       
       
struct AVLTreeNode 
{ 
	AVLTreeNode
       
       
        
        * _left; 
	AVLTreeNode
        
        
          * _right; AVLTreeNode 
         
           * _parent; K _key; V _value; int _bf; // 平衡因子 AVLTreeNode(const K& key,const V& value=V()) :_left(NULL) ,_right(NULL) ,_parent(NULL) ,_key(key) ,_value(value) ,_bf(0) { } }; template 
          
            class AVLTree { public: typedef AVLTreeNode 
           
             Node; AVLTree() :_root(NULL) { } bool Insert(const K& key, const V& value=V()) { if(_root == NULL) { _root = new Node(key,value); return true; } Node* cur = _root; Node* parent = NULL; while(cur) { if(cur->_key > key) { parent = cur; cur = cur->_left; } else if(cur->_key < key) { parent = cur; cur = cur->_right; } else return false; } cur=new Node(key,value); if(parent->_key > key) { parent->_left = cur; cur->_parent=parent; } else { parent->_right = cur; cur->_parent=parent; } while(parent)//调平衡因子 { if(parent->_left == cur ) parent->_bf -- ; else parent->_bf ++ ; if(parent->_bf == 0)//高度没变 break; else if(parent->_bf == 1 || parent->_bf == -1)//逐级调平衡 { cur = parent ; parent = cur->_parent ; } else if(parent->_bf == 2 || parent->_bf == -2)//旋转 { if(parent->_bf == 2)//左旋 { Node* subR = parent ->_right ; if(subR->_bf == 1)//左单旋 { RotateL(parent); return true; } else if(subR->_bf == -1)//右左双旋 { RotateRL(parent); return true; } } else { Node* subL= parent->_left ; if(subL->_bf == -1)//右单旋 { RotateR(parent); return true; } else if(subL->_bf == 1)//左右双旋 { RotateLR(parent); return true; } } } else assert(false);//平衡因子出错 } return false; } void RotateR(Node* parent) { Node* subL = parent->_left ; Node* subLR = subL->_right ; Node* Parentparent = parent->_parent ; parent->_left = subLR ; parent->_parent = subL; subL->_right = parent ; if(subLR) subLR->_parent = parent ; if(Parentparent==NULL) { _root = subL; _root->_parent = NULL ; } else if(Parentparent->_left == parent) { Parentparent->_left = subL; subL->_parent = Parentparent; } else { Parentparent->_right = subL ; subL->_parent = Parentparent; } parent->_bf = 0; subL->_bf = 0; } void RotateL(Node* parent) { Node* subR = parent->_right ; Node* subRL = subR->_left ; Node* Parentparent = parent->_parent ; parent->_right = subRL ; parent->_parent = subR ; subR->_left = parent ; if(subRL) subRL->_parent = parent ; if(Parentparent==NULL) { subR->_parent = NULL ; _root = subR ; } else if(Parentparent->_left == parent) { Parentparent->_left = subR ; subR->_parent = Parentparent ; } else { Parentparent->_right = subR ; subR->_parent = Parentparent ; } subR->_bf = 0; parent->_bf = 0; } void RotateLR(Node* parent) { Node* subL = parent->_left ; Node* subLR = subL->_right ; int bf = subLR->_bf ; RotateL(subL); RotateR(parent); if(bf == 0) { parent->_bf = subL->_bf = subLR->_bf = 0; } else if(bf == 1) { parent->_bf = 0 ; subL->_bf = -1; subLR->_bf = 0; } else if(bf == -1) { parent->_bf = 1; subL->_bf = 0; subLR->_bf = 0; } else assert(false); } void RotateRL(Node* parent) { Node* subR = parent->_right ; Node* subRL = subR->_left ; int bf = subRL->_bf ; RotateR(parent->_right); RotateL(parent); if(bf == 0) { parent->_bf = subR->_bf = subRL->_bf = 0; } else if(bf == 1) { parent->_bf = -1 ; subR->_bf = 0; subRL->_bf = 0; } else if(bf == -1) { parent->_bf = 0; subR->_bf = 1; subRL->_bf = 0; } else assert(false); } void InOrder() { _InOrder(_root); cout< 
            
              _left,left)) return false; int right = 0; if(!_IsBalance(root->_right,right)) return false; height = left > right ? left + 1 : right + 1 ; //高度 return abs(left - right) < 2 ; } //bool _IsBalance(Node* root) //{ // if(root == NULL) // return true; // size_t left = Height(root->_left); // size_t right= Height(root->_right); // return abs(left - right)<2 && // _IsBalance(root->_left) && _IsBalance(root->_right); //} //size_t Height(Node* root) //{ // if(root == NULL) // return 0; // size_t left = Height(root->_left); // size_t right = Height(root->_right); // return left > right ? left+1 : right+1 ; //} void _InOrder(Node* root) { if(root==NULL) return; _InOrder(root->_left); cout< 
             
               _key<<" "; _InOrder(root->_right); } private: Node* _root; }; 
              
             
            
           
          
        
       
       
      
      
     
     
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值