//---------------------------15/03/19----------------------------
/*
插入操作:
如同普通树的插入一样,向RB_tree中插入一个节点,并把他着色成红色
因为红色不会改变树的黑高,然后重新对其进行颜色的改变以及旋转
*/
//插入
RB_INSERT(T,z)
{
y=T.nil;
x=T.root; //初始化要查找的元素
//循环查找要插入的位置,到最后,y就是要插入位置的父亲
while(x!=T.nil)
{
y=x;
if(z.key<x.key)
x=x.left;
else
x=x.right;
}
//设置好z的父亲
z.p=y;
//y==T.nil -->>T中没有节点,可以直接把根节点设置为z
//再根据值的大小来选择是插入左边还是右边
if(y==T.nil)
{
T.root=z;
}
else if(z.key<y.key)
{
y.left=z;
}
else
{
y.right=z;
}
//设置好z的其他属性
z.left=T.nil;
z.right=T.nil;
z.color=RED;
RB_INSERT_FIXUP(T,z);
}
//修复
RB_INSERT_FIXUP(T,z)
{
//只要z的父亲是红的就一直不断向上调整
while(z.p.color==RED)
{
if(z.p==z.p.p.left)
{
y=z.p.p.right;
//case1: y==RED 最好的情况,只需要把z.p和y的颜色调整为黑色,z.p.p调整为红色
if(y.color==RED)
{
z.p.color==BLACK;
y.color=BLACK;
z.p.p.color=RED;
z=z.p.p;
}
else
{
// y!=RED 无法合并颜色 职能通过转换,
//case2: 如果z z.p z.p.p 不在一条直线上 就左转z.p 先把它们换到一条直线上
//而且要保证z指向最底下的一个节点,z.p在经过旋转后会成为这个节点,所以要使z=z.p;
if(z==z.p.right)
{
z=z.p;
LEFT_ROTATE(T,z);
}
//case3: 三个节点已经在一条直线上了,就可以右转z.p.p
//这里节点颜色的改变有点难理解,z.p最终会上升到原来z.p.p的高度
//z.p就需要从红色变成黑色,不然z.p底下的节点就不能保证原来的黑高了
//这样也就要求z.p.p要变成红色,不然z.p.p底下的节点黑高就会+1
z.p.color=BLACK;
z.p.p.color=RED;
RIGHT_ROTATE(T,z.p.p);
}
}
else
{
y=z.p.p.left;
if(y.color==RED)
{
z.p.color==BLACK;
y.color=BLACK;
z.p.p.color=RED;
z=z.p.p;
}
else
{
if(z==z.p.left)
{
z=z.p;
RIGHT_ROTATE(T,z);
}
z.p.color=BLACK;
z.p.p.color=RED;
LEFT_ROTATE(T,z.p.p);
}
}
}
}