1. 任何一个节点都被着色――红色或是黑色。
2. 根节点是黑色的。
3. 所有的NIL节点都看成黑色(NIL节点是就是一个假想的或是无实在意义的节点,所有应该指向NULL的指针,都看成指向了NIL节点。包括叶节点的子节点指针或是根节点的父指针)。
4. 如果一个节点是红色的,那么它的子节点一定是黑色的。
5. 对于任何一个节点而言,从该节点到它的子孙节点中的NIL节点路径中,所包含的黑节点个数相同。
注意理解性质3和5。enum COLOR {RED,BLACK}; struct RB_Node { RB_Node *right,*left,*parent; COLOR RB_COLOR; int key; int data; RB_Node() { right = left = parent = NULL; } }*root,*NIL; NIL = new RB_Node(); root = NIL; NIL->right = root; NIL->left = root; NIL->parent = root; NIL->RB_COLOR = BLACK;//每个叶子节点(NIL)是黑色的
LEFT-ROTATE(T, x) 1 y ← right[x] //Set y. 2 right[x] ← left[y] //Turn y's left subtree into x's right subtree. 3 p[left[y]] ← x 4 p[y] ← p[x] // Link x's parent to y. 5 if p[x] = nil[T] 6 then root[T] ← y 7 else if x = left[p[x]] 8 then left[p[x]] ← y 9 else right[p[x]] ← y 10 left[y] ← x // Put x on y's left. 11 p[x] ← y
bool RB_LeftRotate(RB_Node *x) { //旋转节点x 或 旋转节点的右节点是NIL则不能左旋 if(x == NIL || x->right == NIL) return false; //这里旋转的是x和y=x->right节点使其交换位置 但是二叉查找树的结构不能改变 RB_Node *y = x->right;//找到左旋节点的右子节点 y->parent = x->parent;//改变y节点的父节点,就应该是x的父节点 x->right = y->left;//这里根据二叉查找树的结构性质,y的左子树值肯定大于y的父节点x的值,所以x->right = y->left //这里要处理父亲节点的问题,如果y->left != NIL那么就把起父节点设定为x if(y->left != NIL) y->left->parent = x; //接下来需要处理的是y节点位置的问题,我们所过y节点最后将变为x节点的父节点 //首先判断x->parent是否是NIL,是的话就说明x节点是整个树的根 if(x->parent == NIL) { root = y; NIL->left = root; NIL->right = root; } //不是NIL else { //判断旋转节点x是其父节点的左节点还是右节点 if(x == x->parent->left) { x->parent->left = y; } else { x->parent->right = y; } } //下面把旋转节点x的父节点设定为y,y的左节点为x x->parent = y; y->left = x; return true; }
bool RB_RightRotate(RB_Node *x) { if(x == NIL || x->left == NIL) return false; RB_Node *y = x->left; y->parent = x->parent; x->left = y->right; if(y->right != NIL) y->right->parent = x; if(x->parent == NIL) { root = y; NIL->left = NIL->right = root; } else { if(x == x->parent->right) { x->parent->right = y; } else { x->parent->left = y; } } x->parent = y; y->right = x; return true; }