红黑树删除操作:
红黑树要删除某个key值时,首先还是要查找该key值在树中的位置,查找方法和搜索二叉树方法相同.
要删除的结点分为两种情况:
1.有左右两个孩子都存在.两个孩子都存在时,在该节点的右子树中寻找其直接后继,找到后用其值替换要删除节点的值,然后问题转化为删除该节点的直接后继,直接后继是有一个右孩子或者没有孩子节点.
2.只有一个孩子或者没有子孩子.
以上两种均归纳为最多只有一个孩子节点的节点,只要将其仅有的一个孩子节点及其子树或者NULL直接提上来就行,删除的节点如果是红色则不会影响树的黑高,如果是黑色节点,则会影响树的黑高,树的平衡必然被打破,所以要进行调整.
现在将前面所说的提上来的节点(也就是删除节点的孩子节点,即删除了那个节点以后那个位置上的节点)以下称为x, x 的兄弟节点记为w,如果x为红色节点则直接将红色节点更改为黑色,则又重新平衡,调整完成,如果x为黑色节点(即NULL)这种情况比较复杂 ,分为4种情况处理:
1.如果x的兄弟节点w是红色的,则x和w的父亲节点p一定是黑色的而且w的两个孩子也是黑色的(非null)则只要将p和w做一次左旋转并改变w的颜色为红色即平衡.
2.x的兄弟节点w是黑色(非NULL)且两个子节点是黑色(null),则将w变为红色,这样p节点的子树平衡.将x = x->parent,即上移,又回到了1.2.3.4的情况(以new 的x的子树还是少了一个黑色节点)同样的去检查,如果x为红色则将变为黑色调整完成,如果是黑色,则继续去检查x的new的兄弟节点是什么颜色.....
3.w的左孩子节点是红色,右节点是黑色(null),w和x的父亲节点p可红可黑,对w做一次左旋转,并调整颜色,则成为4的情况.
4.w的右孩子是红色,左边孩子是黑色(null).将x的父亲节点做一次左旋转,然后更改颜色,x的父亲p 为黑色,w为红色,则调整完成.
typedef int Type;
typedef enum{RED=0, BLACK}COLOR;
typedef struct RBNode
{
COLOR color;
Type data;
RBNode *parent;
RBNode *leftChild;
RBNode *rightChild;
}RBNode;
typedef struct RBTree
{
RBNode *root;
RBNode *NIL;
}RBTree;
RBNode* _Buynode(Type v)
{
RBNode *s = (RBNode*)malloc(sizeof(RBNode));
assert(s != NULL);
memset(s, 0, sizeof(RBNode));
s->data = v;
s->color = RED;
return s;
}
void InitRBTree(RBTree &t)
{
t.NIL = _Buynode(0);
t.root = t.NIL;
t.NIL->color = BLACK;
}
void LeftRotate(RBTree &t, RBNode *p)
{
RBNode *s = p->rightChild;
p->rightChild = s->leftChild;
if(s->leftChild != t.NIL)
s->leftChild->parent = p;
s->parent = p->parent;
if(p->parent == t.NIL)
t.root = s;
else if(p == p->parent->leftChild)
p->parent->leftChild = s;
else
p->parent->rightChild = s;
s->leftChild = p;
p->parent = s;
}
void RightRotate(RBTree &t, RBNode *p)
{
RBNode *s = p->leftChild;
p->leftChild = s->rightChild;
if(s->rightChild != t.NIL)
s->rightChild->parent = p;
s->parent = p->parent;
if(p->parent == t.NIL)
t.root = s;
else if(p == p->parent->leftChild)
p->parent->leftChild = s;
else
p->parent->rightChild = s;
s->rightChild = p;
p->parent = s;
}
void Insert_Fixup(RBTree &t, RBNode *z)
{
RBNode *y;
while(z->parent->color == RED)
{
if(z->parent == z->parent->parent->leftChild)
{
y = z->parent->parent->rightChild;
if(y->color == RED)
{
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
continue;
}
else if(z == z->parent->rightChild)
{
z = z->parent;
LeftRotate(t, z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
RightRotate(t, z->parent->parent);
}
else
{
y = z->parent->parent->leftChild;
if(y->color == RED)
{
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
continue;
}
else if(z == z->parent->leftChild)
{
z = z->parent;
RightRotate(t, z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
LeftRotate(t, z->parent->parent);
}
}
t.root->color = BLACK;
}
bool Insert(RBTree &t, Type x)
{
RBNode *pr = t.NIL;
RBNode *s = t.root;
while(s != t.NIL)
{
if(x == s->data)
return false;
pr = s;
if(x < s->data)
s = s->leftChild;
else
s = s->rightChild;
}
RBNode *q = _Buynode(x);
q->parent = pr;
q->leftChild = t.NIL;
q->rightChild = t.NIL;
q->color = RED;
if(pr == t.NIL)
t.root = q;
else if(x < pr->data)
pr->leftChild = q;
else
pr->rightChild = q;
Insert_Fixup(t, q);
return true;
}
RBNode* _Next(RBTree &t, RBNode *p)
{
if(p!=t.NIL && p->rightChild!=t.NIL)
{
p = p->rightChild;
while(p->leftChild != t.NIL)
p = p->leftChild;
}
return p;
}
void Delete_Fixup(RBTree &t, RBNode *&x)
{
RBNode *w;
while(x!=t.root && x->color==BLACK)
{
if(x == x->parent->leftChild)
{
w = x->parent->rightChild;
if(w->color == RED)
{
w->color = BLACK;
x->parent->color = RED;
LeftRotate(t, x->parent);
}
if(w->leftChild->color==BLACK && w->rightChild->color==BLACK)
{
w->color = RED;
x = x->parent;
}
else if(w->rightChild->color == BLACK)
{
w->leftChild->color = BLACK;
w->color = RED;
RightRotate(t, w);
w = x->parent->rightChild;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->rightChild->color = BLACK;
LeftRotate(t, x->parent);
x = t.root;
}
else
{
w = x->parent->leftChild;
if(w->color == RED)
{
w->color = BLACK;
x->parent->color = RED;
RightRotate(t, x->parent);
}
if(w->leftChild->color==BLACK && w->rightChild->color==BLACK)
{
w->color = RED;
x = x->parent;
}
else if(w->leftChild->color == BLACK)
{
w->rightChild->color = BLACK;
w->color = RED;
LeftRotate(t, w);
w = x->parent->leftChild;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->leftChild->color = BLACK;
RightRotate(t, x->parent);
x = t.root;
}
}
x->color = BLACK;
}
bool Remove(RBTree &t, Type key)
{
RBNode *p = t.root;
RBNode *y;
RBNode *s;
while(p!=t.NIL && p->data!=key)
{
if(key < p->data)
p = p->leftChild;
else
p = p->rightChild;
}
//if(p->leftChild!=t.NIL || p->rightChild!=t.NIL)
// y = p;
//else
// y = _Next(t, p);
if(p->leftChild!=t.NIL && p->rightChild!=t.NIL)
y = _Next(t, p);
else
y = p;
if(y->leftChild != t.NIL)
s = y->leftChild;
else
s = y->rightChild;
s->parent = y->parent;
if(y->parent == t.NIL)
t.root = s;
else if(y == y->parent->leftChild)
y->parent->leftChild = s;
else
y->parent->rightChild = s;
if(y != p)
p->data = y->data;
if(y->color == BLACK)
Delete_Fixup(t, s);
delete y;
return true;
}
tianxintong@txt:~/git/shujia/Code@Bao/Test7_13_RBTree_C$