一、AVL树规则
1、AVL树是按照搜索树规则进行插入的
2、更新插入节点的祖先节点的平衡因子
(1)插入父亲的左边,父亲的平衡因子--
(2)插入父亲的右边,父亲的平衡因子++
(3)父亲的平衡因子 == 0,父亲所在的子树高度不变,不再继续往上更新,插入结束了
(3)父亲的平衡因子 == 1 or -1,父亲所在的子树高度变了,继续往上更新
(3)父亲的平衡因子 == 2 or -2,父亲所在的子树不平衡了,需要旋转处理了
更新只会出现 0 1和-1 2和-2 这三种情况,插入之前树是AVL树,插入之后也还是AVL树
二、具体代码
AVL树:
template<class K,class V>
struct AVLTreeNode
{
AVLTreeNode<K,V>* _left;
AVLTreeNode<K,V>* _right;
AVLTreeNode<K,V>* _parent;
pair<K,V> _kv;
int _bf;AVLTreeNode(const pair<K,V>&_kv)
:_left(nullptr)
,_right(nullptr)
,_kv(kv)
,_bf(0)
{}
};template<class K,class V>
class AVLTree
{
typedef BSTreeNode<K,V> Node;
public:
bool Insert(const pair<K,V>&_kv)
{
if(_root == nullptr)
{
_root = new Node(kv);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while(cur)
{
if(cur->_kv.first < kv.first)
{
parent = cur;
cur = cur -> _right;
}
else i f(cur->_kv.first > kv.first)
{
parent = cur;
cur = cur -> _left;
}
else
{
return false;
}
}
cur = new Node(kv);
if(parent->_kv.first < kv.first)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;//更新
while(parent)
{
if(cur == parent->_left)
{
parent ->_bf--;
}
else
{
parent ->_bf++;
}
if(parent->_bf == 0)
{
break;//更新结束
}
else if(parent->_bf == 1 || parent->_bf == -1)
{
//继续往上更新
cur = parent;
parent = parent ->_parent;
}
else if(parent->_bf == 2 || parent->_bf == -2)
{
//当前子树出现问题了,需要旋转平衡
if(parent->_bf == -2 && cur->_bf == -1)
{
RotateR(parent);
}
else if(parent->_bf == 2 && cur->_bf == 1)
{
RotateL(parent);
}
else if(parent->_bf == 2 && cur->_bf == -1)
{
RotateRL(parent);
}
else if(parent->_bf == -2 && cur->_bf == 1)
{
RotateLR(parent);
}
break;
}
else
{
assert(false);
}
}return true;
}
Node* Find(const K& key)
{
if(_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
while(cur)
{
if(cur->_kv.first < key)
{
cur = cur -> _right;
}
else i f(cur->_kv.first > key)
{
cur = cur -> _left;
}
else
{
return cur;
}
}
return nullptr;
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;parent->_left = subLR;
if(subLR)
subLR->_parent = parent;
subL->_right = parent;Node* ppNode = parent->_parent;
parent->_parent = subL;
if(parent == _root)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if(ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}subL->_parent = ppNode;
}
parent->_bf = subL->_bf = 0;
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;parent->_right = subRL;
if(subRL)
subRL->_parent = parent;
subR->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = subR;
if(parent == _root)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if(ppNode->_right == parent)
{
ppNode->_right = subR;
}
else
{
ppNode->_left = subR;
}subR->_parent = ppNode;
}
parent->_bf = subR->_bf = 0;
}
void RotateRL(Node* parent)
{
Node* subR = parent ->_right;
Node* subRL = subL->_left;
int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);if(bf == -1)
{
subRL->_bf = 0;
subR->_bf = 1;
parent->_bf = 0;
}
else if(bf == 1)
{
subRL->_bf = 0;
subR->_bf = 0;
parent->_bf = -1;
}
else if(bf == 0)
{
subRL->_bf = 0;
subR->_bf = 0;
parent->_bf = 0;
}
else
{
assert(false);
}
}void RotateLR(Node* parent)
{
Node* subL = parent ->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;RotateL(parent->_left);
RotateR(parent);if(bf == -1)
{
subLR->_bf = 0;
subL->_bf = 0;
parent->_bf = 1;
}
else if(bf == 1)
{
subLR->_bf = 0;
subL->_bf = -1;
parent->_bf = 0;
}
else if(bf == 0)
{
subLR->_bf = 0;
subL->_bf = 0;
parent->_bf = 0;
}
else
{
assert(false);
}
}bool IsBalance()
{
return IsBalance(_root);
}
int Height()
{
return _Height(_root);
}
int Size()
{
return _Size(_root);
}private:
int _Size(Node* _root)
{
return root == nullptr ? 0 : _Size(root->_left) + _Size(root->_right) + 1;
}bool _IsBalance()
{
if(root == nullptr)
return true;
int leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);
if(abs(leftHeight-rightHeight) >= 2) return false;
//顺便检查一下平衡因子
if(leftHeight-rightHeight != root->_bf)
{
return false;
}return IsBalance(root->_left)
&&IsBalance(root->_right);
}int _Height(Node*root)
{
if(root == nullptr)
return 0;
int leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);return max((_Height(root->_left),_Height(root->_right)) + 1
}Node* _root = nullptr;
};