一、 AVL树的概念。
- AVL树是高度平衡化的二叉搜索树,首先AVL树包括二叉搜索树的一切性质,且满足保证每个结点的左右子树高度之
差的绝对值不超过1(需要对树中的结点进行调整)。也就是降低树的高度。
- 它的左右子树都是AVL树。
- 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)。
- 如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在log2N ,搜索时
间复杂度O( log2N)。
二、AVL树的操作。
(一)AVL树的插入:
- 按照二叉搜索树的方式插入新节点。
- 调整节点的平衡因子。(调整平衡因子就是将各个节点的平衡因子绝对值调至小于等于1)
(二)AVL树的删除:
- AVL树的删除:可按照二叉搜索树的方式将节点删除,然后再更新平衡因子,只不错与删除不同的时,删除节点后的平衡因子更新,最差情况下一直要调整到根节点的位置。
(三)AVL树的平衡调整:
- 第一种情况:向右旋转。(向左直线)
实现代码:
void RotateR(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subR = ptr;
ptr = subR->leftChild;
subR->leftChild = ptr->rightChild;
ptr->rightChild = subR;
ptr->bf = subR->bf = 0;
}
- 第二种情况:向左旋转。(向右直线)
实现代码:
void RotateL(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subL = ptr;
ptr = subL->rightChild;
subL->rightChild = ptr->leftChild;
ptr->leftChild = subL;
ptr->bf = subL->bf = 0;
}
- 第三种情况:先左后右旋转。(向左拐)
实现代码:
void RotateLR(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subL = ptr->leftChild;
AVLNode<Type> *subR = ptr;
ptr = subL->rightChild;
subL->rightChild = ptr->leftChild;
ptr->leftChild = subL;
if (ptr->bf <= 0)
subL->bf = 0;
else
subL->bf = -1;
subR->leftChild = ptr->rightChild;
ptr->rightChild = subR;
if (ptr->bf >= 0)
subR->bf = 0;
else
subR->bf = 1;
ptr->bf = 0;
}
- 第四种情况:先右后左旋转。(向右拐)
实现代码:
void RotateRL(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subL = ptr;
AVLNode<Type> *subR = ptr->rightChild;
ptr = subR->leftChild;
subR->leftChild = ptr->rightChild;
ptr->rightChild = subR;
if (ptr->bf >= 0)
subR->bf = 0;
else
subR->bf = 1;
subL->rightChild = ptr->leftChild;
ptr->leftChild = subL;
if (ptr->bf <= 0)
subL->bf = 0;
else
subL->bf = -1;
ptr->bf = 0;
}
三、AVL树的模拟实现。
- AVL树的节点定义:
template<typename Type>
class AVLTree;
template<typename Type>
class AVLNode
{
friend class AVLTree<Type>;
public:
AVLNode(Type d = Type(), AVLNode<Type>*left = nullptr, AVLNode<Type>*right = nullptr)
: data(d), leftChild(left), rightChild(right), bf(0)
{}
~AVLNode()
{}
private:
Type data;
AVLNode<Type> *leftChild;
AVLNode<Type> *rightChild;
int bf;
};
- AVL树的定义:
template<typename Type>
class AVLTree
{
public:
AVLTree() : root(nullptr)
{}
public:
bool Insert(const Type &x);
bool Remove(const Type &key);
protected:
bool Insert(AVLNode<Type> *&t, const Type &x);
bool Remove(AVLNode<Type> *&t, const Type &key);
protected:
void RotateR(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subR = ptr;
ptr = subR->leftChild;
subR->leftChild = ptr->rightChild;
ptr->rightChild = subR;
ptr->bf = subR->bf = 0;
}
void RotateL(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subL = ptr;
ptr = subL->rightChild;
subL->rightChild = ptr->leftChild;
ptr->leftChild = subL;
ptr->bf = subL->bf = 0;
}
void RotateRL(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subL = ptr;
AVLNode<Type> *subR = ptr->rightChild;
ptr = subR->leftChild;
subR->leftChild = ptr->rightChild;
ptr->rightChild = subR;
if (ptr->bf >= 0)
subR->bf = 0;
else
subR->bf = 1;
subL->rightChild = ptr->leftChild;
ptr->leftChild = subL;
if (ptr->bf <= 0)
subL->bf = 0;
else
subL->bf = -1;
ptr->bf = 0;
}
void RotateLR(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subL = ptr->leftChild;
AVLNode<Type> *subR = ptr;
ptr = subL->rightChild;
subL->rightChild = ptr->leftChild;
ptr->leftChild = subL;
if (ptr->bf <= 0)
subL->bf = 0;
else
subL->bf = -1;
subR->leftChild = ptr->rightChild;
ptr->rightChild = subR;
if (ptr->bf >= 0)
subR->bf = 0;
else
subR->bf = 1;
ptr->bf = 0;
}
private:
AVLNode<Type> *root;
};
- 插入接口实现:
template<typename Type>
bool AVLTree<Type>::Insert(const Type &x)
{
return Insert(root, x);
}
template<typename Type>
bool AVLTree<Type>::Insert(AVLNode<Type> *&t, const Type &x)
{
stack<AVLNode<Type> *> st;
AVLNode<Type> *p = t;
AVLNode<Type> *pr = nullptr;
while (p != nullptr)
{
if (x == p->data)
return false;
pr = p;
st.push(pr);
if (x < p->data)
p = p->leftChild;
else
p = p->rightChild;
}
p = new AVLNode<Type>(x);
if (pr == nullptr)
{
t = p;
return true;
}
if (x < pr->data)
pr->leftChild = p;
else
pr->rightChild = p;
while (!st.empty())
{
pr = st.top();
st.pop();
if (pr->leftChild == p)
pr->bf--;
else
pr->bf++;
if (pr->bf == 0)
break;
if (pr->bf == 1 || pr->bf == -1)
p = pr;
else
{
if (pr->bf > 0)
{
if (p->bf > 0)
{
RotateL(pr);
}
else
{
RotateRL(pr);
}
}
else
{
if (p->bf < 0)
{
RotateR(pr);
}
else
{
RotateLR(pr);
}
}
break;
}
}
if (st.empty())
{
t = pr;
}
else
{
AVLNode<Type> *q = st.top();
if (pr->data < q->data)
q->leftChild = pr;
else
q->rightChild = pr;
}
return true;
}
- 删除接口实现:
template<class Type>
bool AVLTree<Type>::Remove(AVLNode<Type> *&t, const Type &key)
{
AVLNode<Type> *pr = nullptr;
AVLNode<Type> *p = t, *q;
stack<AVLNode<Type>*> st;
while(p != nullptr)
{
if(key == p->data)
break;
pr = p;
st.push(pr);
if(key < p->data)
p = p->leftChild;
else
p = p->rightChild;
}
if(p == nullptr)
return false;
if(p->leftChild!=nullptr && p->rightChild!=nullptr)
{
pr = p;
st.push(pr);
q = p->rightChild;
while(q->leftChild != nullptr)
{
pr = q;
st.push(pr);
q = q->leftChild;
}
p->data = q->data;
p = q;
}
if(p->leftChild != nullptr)
q = p->leftChild;
else
q = p->rightChild;
if(pr == nullptr)
t = q;
else
{
if(p == pr->leftChild)
pr->leftChild = q;
else
pr->rightChild = q;
while(!st.empty())
{
pr = st.top();
st.pop();
if(p->data < pr->data)
pr->bf++;
else
pr->bf--;
if(pr->bf==1 || pr->bf==-1)
break;
if(pr->bf != 0)
{
if(pr->bf < 0)
q = pr->leftChild;
else
q = pr->rightChild;
if(q->bf == 0)
{
if(pr->bf < 0)
{
RotateR(pr);
pr->bf = 1;
pr->rightChild->bf = -1;
}
else
{
RotateL(pr);
pr->bf = -1;
pr->leftChild->bf = 1;
}
if(!st.empty())
{
AVLNode<Type> *ppr = st.top();
if (ppr->data < pr->data)
ppr->rightChild = pr;
else
ppr->leftChild = pr;
}
else
t = pr;
break;
}
if(pr->bf < 0)
{
if(q->bf < 0)
{
RotateR(pr);
}
else
{
RotateLR(pr);
}
}
else
{
if(q->bf > 0)
{
RotateL(pr);
}
else
{
RotateRL(pr);
}
}
if (!st.empty())
{
AVLNode<Type> *ppr = st.top();
if (ppr->data < pr->data)
ppr->rightChild = pr;
else
ppr->leftChild = pr;
}
else
t = pr;
}
q = pr;
}
}
delete p;
return true;
}
四、AVL树的应用。
- AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度。
但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:
- 插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。
- 如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。