一、AVL树的概念
二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,俩位俄罗斯的数学家G.MAdelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
- 它的左右子树都是AVL树
- 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
如果一颗二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在O(logN),搜索时间复杂度O(logN)。
二、AVL树节点的定义
AVL树节点的定义:
template<class T>
struct AVLTreeNode
{
AVLTreeNode(const T& data)
:_pLeft(nullptr)
{
}
AVLTreeNode<T>* _pLeft; //该节点的左孩子
AVLTreeNode<T>* _pRight; //该节点的右孩子
AVLTreeNode<T>* _pParent; //该节点的双亲
T _data;
int _bf; //该节点的平衡因子
};
三、AVL树的插入
AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么AVL树的插入过程可以分为两步:
- 按照二叉搜索树的方式插入新节点
bool Insert(const T& data)
{
//1. 先按照二叉搜索树的规则将节点插入到AVL树中
if (nullptr == _pRoot)
{
_pRoot = new Node(data);
return true;
}
//按照二叉搜索树的性质找data在AVL中的插入位置
PNode pCur = _pRoot;
PNode pParent = nullptr;
while (pCur)
{
pParent = pCur;
if (data < pCur->_data)
pCur = pCur->pLeft;
else if (data > pCur->_data)
pCur = pCur->pRight;
else
return