数据结构——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.1)AVL树的插入
在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; };