AVL树
AVL树的概念
AVL树是二叉搜索树,它的左右子树高度之差(简称平衡因子)的绝对值不超过1,并且左右子树也是AVL树,AVL树是高度平衡的,如果有n个节点,其高度可保持在 l o g 2 N log_2N log2N搜索时间复杂度是 l o g 2 N log_2N log2N。
AVL树节点的定义
template<class T>
struct AVLTreeNode
{
AVLTreeNode(const T& data)
: _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr)
, _data(data), _bf(0)
{}
AVLTreeNode<T>* _pLeft; // 该节点的左孩子
AVLTreeNode<T>* _pRight; // 该节点的右孩子
AVLTreeNode<T>* _pParent; // 该节点的双亲
T _data;
int _bf; // 该节点的平衡因子
};
AVL树节点的插入
由于插入时要保持AVL树的平衡,就需要旋转,AVL树的旋转分为左单旋、右单旋、右左双旋、左右双旋,四种旋转方式。
上述两种是右单旋和左单旋,右单旋是插入新节点后左边子树高度比右边子树高度大2,故向右旋转保持平衡。左单旋以此类推。
上述两种是左右双旋和右左双旋,这种情况执行单旋已经无法让AVL树保持平衡,必须通过双旋来让AVL树保持平衡。
AVL树的验证
先通过中序遍历验证是否是二叉搜索树,然后再验证平衡星,代码如下:
bool _IsAVLTree(Node* pRoot)
{
if (pRoot == nullptr)return true;
int leftHeight = _Height(pRoot->_pLeft);
int rightHeight = _Height(pRoot->_pRight);
if (abs(rightHeight - leftHeight) >= 2)
{
cout << pRoot->_data << "不平衡" << endl;
return false;
}
if (rightHeight - leftHeight != pRoot->_bf)
{
cout << pRoot->_data << "平衡因子异常" << endl;
return false;
}
return _IsAVLTree(pRoot->_pLeft) && _IsAVLTree(pRoot->_pRight);
}
size_t _Height(Node* pRoot)
{
if (pRoot == nullptr)return 0;
int leftHeight = _Height(pRoot->_pLeft);
int rightHeight = _Height(pRoot->_pRight);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}