//---------------------------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=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.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); } } } }