左旋:以某个节点作为旋转点,其右子节点变为旋转节点的父节点,右子节点的左子节点变为旋转节点的右子节点,左子节点保持不变。
右旋:以某个节点作为旋转点,其左子节点变为旋转节点的父节点,左子节点的右子节点变为旋转节点的左子节点,右子节点保持不变。
如上图便是左旋的过程,将pr拉上去之后p下去。P做为pr的左节点之后断开rl(因为二叉树),因为rl也需要连接父节点,故最终rl做为p的右子节点。
通过代码来理解左右旋的过程:
/**
* 围绕p左旋
* pf pf
* / /
* p pr(r)
* / \ ==> / \
* pl pr(r) p rr
* / \ / \
* rl rr pl rl
*
* @param p
*/
void leftRotate(RBNode<int, double> p) // 参数为旋转点
{
if (p != NULL)
{
RBNode<int, double> r = p.right;
p.right = r.left;
if (r != NULL)
{
r.left.parent = p;
}
r.parent = p.parent;
if (p.parent == null)
{
root = r;
}
else if (p.parent.left == p)
{
p.parent.left = r;
}
else if (p.parent.right == p)
{
p.parent.right = r;
}
r.left = p;
p.parent = r;
}
else
return;
}
/**
* 右旋
* pf pf
* \ \
* p (l)pl
* / \ => / \
*(l)pl pr ll p
* / \ / \
* ll lr lr pr
*
* @param p
*/
void rightRotate(RBNode<int, double> p)
{
if (p != NULL)
{
RBNode<int, double> l = p.left;
p.left = l.right;
if (l.right != null)
{
l.right.parent = p;
}
l.parent = p.parent;
if (p.parent == NULL)
{
root = l;
}
else if (p.parent.left == p)
{
p.parent.left = l;
}
else if (p.parent.right == p)
{
p.parent.right = l;
}
l.right = p;
p.parent = l;
}
else
return;
}
左右旋算法的实现主要参照代码上注释的那段,便很好理解。注意:左右旋都是旋转顶上的节点,低下的节点随着顶上节点的旋转也会相应的改变。