AVL树
一、概念
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
1、它的左右子树都是AVL树
2、左子树和右子树高度之差(简称平衡因子)的绝对值不超过1
如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在O(lgn),平均搜索时间复杂度O(lg(n))
二、平衡化
如果在一个原本平衡的二叉搜索树中插入一个新节点,可能会导致二叉搜索树不平衡,此时必须调整树的结构使之平衡化。
在插入新的结点时,如果新插入的结点使原本的一些结点的平衡因子的绝对值等于2,这时候就需要用以下四种旋转方法调整不平衡的子树,使得整个树保持平衡:
1、左单旋
插入点位于不平衡节点的右子节点的右子树 -- 右右
2、右单旋
插入点位于不平衡节点的左子节点的左子树 -- 左左
3、左右双旋(先左后右双旋)
插入点位于不平衡节点的左子节点的右子树 -- 左右
4、右左双旋(先右后左双旋)
插入点位于不平衡节点的右子节点的左子树 -- 右左
三、AVL树的插入
在AVL树中插入结点(key,value)的算法:
1. 如果是空树,插入后即为根节点,插入后直接返回true
2. 如果树不空,寻找插入位置,若在寻找的过程中找到key,则插入失败直接返回false
3. 插入结点
4. 更新平衡因子,对树进行调整
新节点pcur平衡因子为0,但其双亲结点parent的平衡因子有三种情况:
1、如果parent的平衡因子为0
即在parent较矮的子树上插入新节点,parent平衡,其高度没有增加,此时从parent到
根路径上各结点为根的子树的高度不变,即各结点的平衡因子不变,结束平衡化处理。
2、如果parent的平衡因子的绝对值为1;
插入前parent的平衡因子为0,插入后以parent为根的子树没有失去平衡,但该子树
的高度增加,需从parent向根节点方向回溯,继续查看parent的双亲的平衡性。
3、在上述2更新后,如果parent平衡因子的绝对值为2,新节点在较高的子树插入,需要
做平衡化处理:
若parent->_bf == 2,说明右子树高,设parent的右子树为subR
当subR的平衡因子为1,执行左单旋转
当subR的平衡因子为-1,执行先右后左双旋转
若parent->_bf == -2,说明左子树高,设parent的左子树为subL
当subL的平衡因子为-1,执行右单旋转
当subL的平衡因子为1,执行先左后右双旋转
旋转后parent为根的子树高度降低,无需继续向上层回溯
四、AVL树的删除
从AVL树中删除一个节点,首先必须检测该结点是否存在,若存在删除该结点之后可能会破坏AVL树的高度平衡,因此需要做平衡化旋转。
被删除的结点pcur存在以下情况:
1、被删除结点只有左孩子
2、被删除结点只有右孩子
3、被删除结点左右孩子都存在-->变为删除中序遍历下的第一个结点q
更新parent的平衡因子,若q是parent的左孩子,则parent的平衡因子增加1,否则减少1,根据修改后的parent的平衡因子调整到根路径上的所有节点:
1、parent平衡因子的平衡因子为1或-1,parent高度不变,则从parent到根所有节点高度均不变,不用调整。
2、parent的平衡因子变成0,虽然以parent为根的子树平衡,其高度减1,但需要检查parent的双亲结点的平衡性。
3、结点parent的平衡因子为2或-2,则较矮子树被缩短,parent发生不平衡,需要进行平
衡化旋转。
令parent较高子树的根为q,根据q的平衡因子,分一下三种情况
a、如果q的平衡因子为0,执行单旋转恢复parent
b、如果q的平衡因子与parent平衡因子(正负)号相同,则执行一个单旋转恢复parent
c、如果q的平衡因子与parent平衡因子(正负)号相反,则执行一个双旋转恢复parent
五、完整代码
对AVL树的删除没有做具体实现。
#include<iostream>
using namespace std;
template<class K, class V>
struct AVLTreeNode
{
AVLTreeNode()
: _left(NULL)
, _right(NULL)
, _parent(NULL)
, _bf(0)
{}
AVLTreeNode(K key, V value)
: _left(NULL)
, _right(NULL)
, _parent(NULL)
, _bf(0)
, _key(key)
, _value(value)
{}
struct AVLTreeNode<K,V>* _left;
struct AVLTreeNode<K,V>* _right;
struct AVLTreeNode<K,V>* _parent;
K _key;
V _value;
int _bf;
};
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K,V> Node;
typedef Node* pNode;
public:
AVLTree()
:_pRoot(NULL)
{}
AVLTree(const K* arr, size_t size)
{
for (size_t i = 0; i < size; ++i)
{
_Insert(_pRoot, arr[i], i);
}
}
void Inorder()
{
_Inorder(_pRoot);
}
bool IsBalance()
{
return _IsBalance(_pRoot);
}
int Height()
{
return _Height(_pRoot);
}
private:
bool _Insert(pNode &pRoot, const K& key, const V& value)
{
if (pRoot == NULL)
{
pRoot = new Node(key, value);
return true;
}
//找插入位置
pNode pCur = pRoot;
pNode parent = NULL;
while (pCur)
{
parent = pCur;
if (pCur->_key > key)
pCur = pCur->_left;
else if (pCur->_key < key)
pCur = pCur->_right;
else
return false;
}
//插入节点
pCur = new Node(key, value);
if (parent->_key > key)
{
parent->_left = pCur;
pCur->_parent = parent;
}
else
{
parent->_right = pCur;
pCur->_parent = parent;
}
while (parent)
{
if (parent->_left == pCur)
parent->_bf--;
else
parent->_bf++;
if (parent->_bf == 0)
break;
else if (parent->_bf == 1 || parent->_bf == -1)
{
if (parent->_parent)
{
pCur = parent;
parent = parent->_parent;
}
else
break;
}
else
{
pNode parentR = parent->_right;
pNode parentL = parent->_left;
if (parent->_bf == -2)
{
if (pCur->_bf == -1)
//右单旋
RotateR(parent);
else if (pCur->_bf == 1)
//左右双旋
RotateLR(parent);
}
if (parent->_bf == 2)
{
if (pCur->_bf == -1)
RotateRL(parent);
//右左双旋
else if (pCur->_bf == 1)
RotateL(parent);
//左单旋
}
else
break;
if (parent->_parent)
{
pCur = parent;
parent = parent->_parent;
}
}
}
return true;
}
bool _IsBalance(pNode pRoot)//判断一个树是否为平衡树
{
if (pRoot == NULL)
return true;
int RHeight = _Height(pRoot->_right);
int LHeight = _Height(pRoot->_left);
if ((RHeight - LHeight) < 2 && (RHeight - LHeight) > -2)
{
_IsBalance(pRoot->_left);
_IsBalance(pRoot->_right);
}
else
return false;
return true;
}
int _Height(pNode &pRoot)//求树的高度
{
if (pRoot == NULL)
return 0;
return (_Height(pRoot->_left) > _Height(pRoot->_right))?_Height(pRoot->_left):_Height(pRoot->_right) + 1;
}
void RotateL(pNode &pRoot)//左单旋
{
pNode pRootR = pRoot->_right;
pNode pRootRL = pRootR->_left;
pRoot->_right = pRootRL;
if (pRootRL)
pRootRL->_parent = pRoot;
pNode pparent = pRoot->_parent;
pRootR->_parent = pparent;
pRoot->_parent = pRootR;
pRootR->_left = pRoot;
if (pRoot != _pRoot)
{
if (pparent->_left == pRoot)
pparent->_left = pRootR;
else
pparent->_right = pRootR;
}
else
_pRoot = pRootR;
pRoot->_bf = pRootR->_bf = 0;
}
void RotateR(pNode &pRoot)//右单旋
{
pNode pRootL = pRoot->_left;
pNode pRootLR = pRootL->_right;
pRoot->_left = pRootLR;
if (pRootLR)
pRootLR->_parent = pRoot;
pRootL->_right = pRoot;
pNode pparent = pRoot->_parent;
pRootL->_parent = pparent;
pRoot->_parent = pRootL;
if (pRoot != _pRoot)
{
if (pparent->_left == pRoot)
pparent->_left = pRootL;
else
pparent->_right = pRootL;
}
else
_pRoot = pRootL;
pRoot->_bf = pRootL->_bf = 0;
}
void RotateRL(pNode &pRoot)//右左双旋
{
pNode pRootR = pRoot->_right;
pNode pRootRL = NULL;
if (pRootR)
pRootRL = pRootR->_left;
RotateR(pRootR);
RotateL(pRoot);
if (pRootRL->_bf == 1)
pRoot->_bf = -1;
else if (pRootRL->_bf == -1)
pRoot->_bf = 0;
}
void RotateLR(pNode &pRoot)//左右双旋
{
pNode pRootL = pRoot->_left;
pNode pRootLR = NULL;
if (pRootL)
pRootLR = pRootL->_right;
RotateL(pRootL);
RotateR(pRoot);
if (pRootLR->_bf == 1)
pRoot->_bf = 0;
else if (pRootLR->_bf == -1)
pRoot->_bf = 1;
}
void _Inorder(pNode pRoot)
{
if (pRoot)
{
_Inorder(pRoot->_left);
cout << pRoot->_key << " " << pRoot->_value << endl;
_Inorder(pRoot->_right);
}
}
pNode _pRoot;
};
int main()
{
int arr[] = {16, 3, 7, 11, 9, 26, 18, 14, 15};
AVLTree<int, int> AVL(arr, 9);
AVL.Inorder();
if (AVL.IsBalance())
cout << "IsBanlanceTree" << endl;
else
cout << "NotIsBanlanceTree" << endl;
cout << "树的高度为" << AVL.Height() << endl;
return 0;
}以下为运行结果:

74

被折叠的 条评论
为什么被折叠?



