二叉搜索树是为了降低遍历的时间复杂度,但是对于单支情况并不能很好的解决,要遍历一个左单支或右单支的二叉树,时间复杂度和链表相同,所以就引入了—>AVL树。
AVL树和一般的搜索二叉树相比有什么不同呢?
AVL树在搜索二叉树的基础上每个节点都加了一个平衡因子。
平衡因子的计算方法就是:右子树的深度 – 左子树的深度,或者也可以是,左子树的深度 – 右子树的深度。
当平衡因子的值 >= 2或<= -2时就需要调整了,而调整的方法就是:旋转。
旋转的方法分为四种:左单旋、右单旋、左右双旋和右左双旋。
左单旋:
对于pParent == 2,
pCur == 1
void _RotateL(Node* pParent)
{
Node* pCur = pParent->_pRight;
Node* pTmp = pCur->_pLeft;
Node* pPParent = pParent->_pParent;
pParent->_pRight = pTmp;
if(pTmp)
pTmp->_pParent = pParent;
pCur->_pLeft = pParent;
pParent->_pParent = pCur;
if(pPParent ==NULL)
_pRoot = pParent;
else
{
if(pPParent->_pLeft == pParent)
pPParent->_pLeft = pCur;
else
pPParent->_pRight = pCur;
}
pCur->_pParent = pPParent;
//更新平衡因子
pParent->_bf = _Height(pParent->_pRight) - _Height(pParent->_pLeft);
pCur->_bf = _Height(pCur->_pRight) - _Height(pCur->_pLeft);
}
右单旋:
pParent == -2, pCur == -1
void _RotateR(Node* pParent)
{
Node* pCur = pParent->_pLeft;
Node* pTmp = pCur->_pRight;
Node* pPParent = pParent->_pParent;
pParent->_pLeft = pTmp;
if(pTmp)
pTmp->_pParent = pParent;
pCur->_pRight = pParent;
pParent->_pParent = pCur;
if(pPParent ==NULL)
_pRoot = pParent;
else
{
if(pPParent->_pLeft == pParent)
pPParent->_pLeft = pCur;
else
pPParent->_pRight = pCur;
}
pCur->_pParent = pPParent;
//更新平衡因子
pParent->_bf = _Height(pParent->_pRight) - _Height(pParent->_pLeft);
pCur->_bf = _Height(pCur->_pRight) - _Height(pCur->_pLeft);
}
左右双旋:
pParent == -2, pCur == 1
左右双旋只需调用左单旋和右单旋即可。
void _RotateLR(Node* pParent)
{
_RotateL(pParent->_pLeft);
_RotateR(pParent);
}
右左双旋:
pParent == 2, pCur==-1
void _RotateRL(Node* pParent)
{
_RotateR(pParent->_pRight);
_RotateL(pParent);
}
整体插入代码:
template<class K, class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
AVLTree()
: _pRoot(NULL)
{}
bool Insert(const K& key, const V& value)
{
if(_pRoot == NULL)
{
_pRoot = new Node(key, value);
return true;
}
Node* pCur = _pRoot;
Node* pParent = NULL;
//先找到要插入的位置
while(pCur)
{
if(pCur->_key > key)
{
pParent = pCur;
pCur = pCur->_pLeft;
}
else if(pCur->_key < key)
{
pParent = pCur;
pCur = pCur->_pRight;
}
else
return false;
}
pCur = new Node(key, value);
//连接pParent与pCur
if(pParent->_key > key)
pParent->_pLeft = pCur;
else
pParent->_pRight = pCur;
pCur->_pParent = pParent;
//调整
while(pParent)
{
//先调整双亲的平衡因子
if(pCur == pParent->_pLeft)
pParent->_bf --;
else
pParent->_bf ++;
if(pParent->_bf == 0)
return true;
//如果双亲的平衡因子是1或-1,说明该子树增加了一层,需要向上调整平衡因子
else if(abs(pParent->_bf) <= 1)
{
pCur = pParent;
pParent = pParent->_pParent;
}
//此时的平衡因子是2或-2,需要进行旋转减小平衡因子
else
{
//右子树较高
if(pParent->_bf == 2)
{
//右子树较高
if(pCur->_bf == 1)
_RotateL(pParent);
else
_RotateRL(pParent);
}
else
{
if(pCur->_bf == 1)
_RotateR(pParent);
else
_RotateLR(pParent);
}
break;
}
}
}
void InOrder()
{
cout<<"InOrder: ";
_InOrder(_pRoot);
cout<<endl;
}
size_t Height()
{
return _Height(_pRoot);
}
bool IsBalanceTree()
{
return _IsBalanceTree(_pRoot);
}
private:
size_t _Height(Node* pRoot)
{
if(pRoot)
{
int HeightLeft = 0;
int HeightRight = 0;
if(pRoot->_pLeft)
HeightLeft = _Height(pRoot->_pLeft);
if(pRoot->_pRight)
HeightRight = _Height(pRoot->_pRight);
return HeightLeft>HeightRight ? HeightLeft+1 : HeightRight+1;
}
return 0;
}
void _InOrder(Node* pRoot)
{
if(pRoot)
{
_InOrder(pRoot->_pLeft);
cout<<pRoot->_key<<" ";
_InOrder(pRoot->_pRight);
}
}
private:
Node* _pRoot;
};
如何判断一个AVL树是否平衡?
用递归的方法先遍历根节点,再遍历左子树,最后遍历右子树。判断根节点时应先判断平衡因子是否正确,再判断平衡因子的绝对值有没有大于1。
bool _IsBalanceTree(Node* pRoot)
{
if(pRoot == NULL)
return true;
if(pRoot->_bf != _Height(pRoot->_pRight) - _Height(pRoot->_pLeft) ||\
abs(pRoot->_bf) >= 2)
return false;
if(pRoot->_pLeft)
_IsBalanceTree(pRoot->_pLeft);
if(pRoot->_pRight)
_IsBalanceTree(pRoot->_pRight);
return true;
}