AVL的旋转
-
AVL树是一棵高度平衡树,树中任何节点的两个子树的高度最大差别为1。
-
我们可以在节点中加入一个变量,该变量用来判断当前节点是否平衡,当该节点的左子树发生变化时,我们可以将平衡因子进行减1,当该节点的右子树发生变化时,我们可以将该节点的平衡因子进行加1。所以当这棵子树平衡时它的平衡因子为0,当平衡因子为2或者-2时,此时就需要进行旋转。
特点
- 本身首先是一颗二叉搜索树。
- 自带平衡条件:每个节点的左右子树高度差不差过1。
节点
template <class K, class V>
struct AVLTreeNode
{
AVLTreeNode* _left;
AVLTreeNode* _right;
AVLTreeNode* _parent;
pair<K, V>_kv;
int _bf;//平衡因子
AVLTreeNode(pair<K, V> val)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(val)
, _bf(0)
{}
};
右单旋
当插入的节点位于较高左子树的左侧时
//右单旋
void RotateR(Node* cur)
{
Node* left = cur->_left;
Node* parent = cur->_parent;
cur->_left = left->_right;
if (cur->_left)
cur->_left->_parent = cur;
left->_right = cur;
cur->_parent = left;
left->_parent = parent;
if (_root == cur) {
_root = left;
}
else {
if (parent->_kv.first > left->_kv.first) {
parent->_left = left;
}
else
parent->_right = left;
}
left->_bf = cur->_bf = 0;
}
左单旋
当插入位置位于较高右子树的右侧时,进行左单旋
void RotateL(Node* cur)
{
Node* right = cur->_right;
Node* parent = cur->_parent;
cur->_right = right->_left;
right->_left = cur;
cur->_parent = right;
if (cur->_right)
cur->_right->_parent = cur;
right->_parent = parent;
if (_root == cur) {
_root = right;
}
else {
if (parent->_kv.first > right->_kv.first)
parent->_left = right;
else
parent->_right = right;
}
cur->_bf = right->_bf = 0;
}
左右双旋
//左旋加右旋
void RotateLR(Node* cur)
{
Node* left = cur->_left;
Node* leftR = left->_right;
int bf = leftR->_bf;
RotateL(left);
RotateR(cur);
if (bf == -1) {
left->_bf = 0;
cur->_bf = 1;
leftR = 0;
}
else if (bf == 1) {
left->_bf = -1;
cur->_bf = 0;
leftR->_bf = 0;
}
else if (bf == 0) {
left->_bf = 0;
cur->_bf = 0;
leftR->_bf = 0;
}
else {
//出错了
assert(false);
}
}
右左双旋
void RotateRL(Node* cur)
{
Node* right = cur->_right;
Node* rightL = right->_left;
int bf = rightL->_bf;
RotateR(right);
RotateL(cur);
if (bf == -1) {
right->_bf = 1;
cur->_bf = 0;
rightL->_bf = 0;
}
else if (bf == 1) {
right->_bf = 0;
cur->_bf = -1;
rightL->_bf = 0;
}
else if (bf == 0) {
right->_bf = 0;
cur->_bf = 0;
rightL->_bf = 0;
}
else {
//出错了
assert(false);
}
}