二叉搜索树的缺点
当二叉树数据是一条直线时,它就变成一个链表,效率极大降低,所以引入了平衡二叉树
AVL树(平衡二叉搜索树)概念
任意结点其左右子树高度相差不大于1
要做到平衡一个二叉树并不容易,在每个结点中放入一个平衡因子,平衡因子来判断是否为平衡二叉树,平衡因子只能等于0 1 -1
如果不是,那么就需要旋转,这个是平衡二叉树最重要的步骤
插入节点
1、插入在左边,parent平衡因子-1 , 插入在右边,parent平衡因子+1
2、当parent为1或-1,需要向上更新祖先节点平衡因子
3、当parent为2或-2,需要进行旋转,更新parent的平衡因子
1.左旋
2.右旋
3.双旋
什么时候需要双旋?
parent平衡因子为2,并且parent,cur,插入节点,三个不在同一直线时,需要双旋
左旋再右旋
这里分为两种情况
1、在curleft左边插入
2、在curlefr右边插入
因为在curleft右边插入后,该节点比curleft要大,左旋之后不能放在curleft的左边
右旋再左旋
与左旋再右旋类似,都会出现两种情况
旋转代码
void RotateL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
cur->_left = parent;
if (curleft)
curleft = parent->_right;
parent->_parent = cur;
parent->_right = curleft;
Node* ppnode = parent->_parent;
//判断parent是否是_root
if (parent == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppnode->_left==parent)//(ppnode->_kv.first > cur->_kv.first)
{
ppnode->_left = cur;
}
else
{
ppnode->_right = cur;
}
cur->_parent = ppnode;
}
parent->_bf = cur->_bf = 0;
}
void RotateR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
cur->_left = parent;
if (curright)
curright = parent->_right;
parent->_parent = cur;
parent->_right = curright;
Node* ppnode = parent->_parent;
//判断parent是否是_root
if (parent == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (ppnode->_left == parent)//(ppnode->_kv.first > cur->_kv.first)
{
ppnode->_left = cur;
}
else
{
ppnode->_right = cur;
}
cur->_parent = ppnode;
}
parent->_bf = cur->_bf = 0;
}
//双旋
//p
// c
//cl
//1、cl平衡因子为0
//2、cl平衡因子为1
//3、cl平衡因子为-1
void RotateRL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
int bf = curleft->_bf;
RotateR(cur);
RotateL(curleft);
if (bf==0)
{
cur->_bf = 0;
parent->_bf = 0;
curleft->_bf = 0;
}
else if (bf == 1)
{
cur->_bf = 0;
parent->_bf = -1;
curleft->_bf = 0;
}
else if(bf == -1)
{
cur->_bf = 1;
parent->_bf = 0;
curleft->_bf = 0;
}
else
{
assert(false);
}
}
// p
//c
// cr
void RotateLR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
int bf = curright->_bf;
RotateL(cur);
RotateR(curright);
if (bf == 0)
{
cur->_bf = 0;
parent->_bf = 0;
curright->_bf = 0;
}
else if (bf == 1)
{
cur->_bf = 0;
parent->_bf = -1;
curright->_bf = 0;
}
else if (bf == -1)
{
cur->_bf = -1;
parent->_bf = 0;
curright->_bf = 0;
}
else
{
assert(false);
}
}