/*
性质1. 节点是红色或黑色
性质2. 根是黑色
性质3. 每个红色节点的两个子节点都是黑色 (从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点
*/
#include<iostream>
using namespace std;
typedef int KeyType;
typedef enum Color //定义红黑树结点颜色颜色类型
{
RED = 0,
BLACK = 1
}Color;
typedef struct
{
KeyType key;
}DataType;
typedef struct RBTreeNode
{
DataType elem;
struct RBTreeNode *lchild;
struct RBTreeNode *rchild;
struct RBTreeNode *parent;
Color color;
}RBTreeNode,*RBTree;//红黑树节点
RBTreeNode *nil=NULL; //为了避免讨论结点的边界情况,定义一个nil结点代替所有的NULL
RBTreeNode* Parent(RBTreeNode *t)
{
return t->parent;
}
RBTreeNode* Left(RBTreeNode *t)
{
return t->lchild;
}
RBTreeNode* Right(RBTreeNode *t)
{
return t->rchild;
}
void LeftRotate(RBTree &T, RBTreeNode *x) //左旋转:结点x原来的右子树y旋转成为x的父母
{
if(x->rchild != nil)
{
RBTreeNode *y = Right(x);
x->rchild = y->lchild;
if(y->lchild != nil)
{
y->lchild->parent = x;
}
y->parent = x->parent;
if(x->parent == nil)
{
T = y;
}
else
{
if(x == Left( Parent(x) ))
{
x->parent->lchild = y;
}
else
{
x->parent->rchild = y;
}
}
y->lchild = x;
x->parent = y;
}
else
{
cout<<"右子树为空,不能执行左旋!"<<endl;
}
}
void RightRotate(RBTree &T, RBTreeNode *x) //右旋转:结点x原来的左子树y旋转成为x的父母
{
if(x->lchild != nil)
{
RBTreeNode *y = Left(x);
x->lchild = y->rchild;
if(y->rchild != nil)
{
y->rchild->parent = x;
}
y->parent = x->parent;
if(x->parent == nil)
{
T = y;
}
else
{
if(x == Left( Parent(x) ))
{
x->parent->lchild = y;
}
else
{
x->parent->rchild = y;
}
}
y->rchild = x;
x->parent = y;
}
else
{
cout<<"左子树为空,不能执行右旋!"<<endl;
}
}
void RBInsertFixup(RBTree &T, RBTreeNode *z) //插入结点后, 要维持红黑树四条性质的不变性
{
RBTreeNode *y;
while(Parent(z)->color == RED)//因为插入的结点是红色的,所以只可能违背性质3,即假如父结点也是红色的,要做调整
{
if( Parent(Parent(z))->lchild == Parent(z) ) //如果要插入的结点z是其父结点的左子树
{
y = Parent(Parent(z))->rchild;//y设置为z的叔父节点
if( y->color == RED)//case 1:如果y的颜色为红色,那么将y与z的父亲同时着为黑色,然后把z的祖父变为红色,这样子z的祖父结点可能违背性质3,将z上移成z的祖父结点
{
y->color = BLACK;
z->parent->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else
{
if( z == z->parent->rchild)//case 2: 如果y的颜色为黑色,并且z是z的父母的右结点,则z左旋转,并且将z变为原来z的parent.
{
z = z->parent;
LeftRotate(T, z);
}
//case 3: 如果y的颜色为黑色,并且z是z的父母的左结点,那么将z的父亲的颜色变为黑,将z的祖父的颜色变为红,然后旋转z的祖父
z->parent->color = BLACK;
z->parent->parent->color = RED;
RightRotate(T, z->parent->parent);
}
}
else //与前一种情况对称
{
y = Parent(Parent(z))->lchild;
if( y->color == RED)
{
y->color = BLACK;
z->parent->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else
{
if( z == z->parent->lchild)
{
z = z->parent;
RightRotate(T, z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
LeftRotate(T, z->parent->parent);
}
}
}
T->color = BLACK; //最后如果上升为T的根的话,把T的颜色设置为黑色
}
void RBInsert(RBTree &T, KeyType key) //插入结点
{
if(T == NULL)
{
T = (RBTree)malloc(sizeof(RBTreeNode));
nil = (RBTreeNode*)malloc(sizeof(RBTreeNode));
nil->color = BLACK;
T->lchild = nil;
T->rchild = nil;
T->parent = nil;
T->elem.key = key;
T->color = BLACK;
}
else
{
RBTreeNode *x = T;//用p保存当前顶点的父母结点,用x保存当前要插入的结点
RBTreeNode *p = nil;
while(x != nil)
{
p = x;
if(key < x->elem.key)
x = x->lchild;
else if(key > x->elem.key)
x = x->rchild;
else //如果查找到与key值相同的结点,则什么也不做,直接返回
{
cout<<"重复值,插入失败!"<<endl;
return ;
}
}
x = (RBTreeNode*)malloc(sizeof(RBTreeNode));
x->color = RED;
x->lchild = nil;
x->rchild = nil;
x->parent = p;
x->elem.key = key;
if(key < p->elem.key)
p->lchild = x;
else
p->rchild = x;
RBInsertFixup(T, x);
}
}
RBTreeNode* Successor(RBTree &T, RBTreeNode *x) //寻找结点x的中序后继
{
if(x->rchild != nil)//如果x的右子树不为空,那么为右子树中最左边的节点
{
RBTreeNode *p = x->rchild;
while(p->lchild != nil)
{
p = p->lchild;
}
return p;
}
else //如果x的右子树为空,那么x的后继为x的所有祖先中为左子树的祖先
{
RBTreeNode *y = x->parent;
while(y != nil && x == y->rchild)
{
x = y;
y = y->parent;
}
return y;
}
}
void RBDeleteFixup(RBTree &T, RBTreeNode *x) //删除黑色结点后,导致黑色缺失,违背性质4,故对树进行调整
{
while(x != T && x->color == BLACK)//如果x是红色,则直接把x变为黑色跳出循环,这样子刚好补了一重黑色,也满足了性质4
{
if(x == x->parent->lchild)
{
RBTreeNode *w = x->parent->rchild;
if(w->color == RED)//case 1: 如果w的颜色为红色的话
{
w->color = BLACK;
x->parent->color = RED;
LeftRotate(T, x->parent);
w = x->parent->rchild;
}
if(w->lchild->color == BLACK && w->rchild->color ==BLACK)//case 2: w的颜色为黑色,其左右子树的颜色都为黑色
{
w->color = RED;
x = x->parent;
}
else if(w->rchild->color == BLACK)//case 3: w的左子树是红色,右子树是黑色的话
{
w->color = RED;
w->lchild->color = BLACK;
RightRotate(T, w);
w = x->parent->rchild;
}
w->color = x->parent->color; //case 4: w的右子树是红色
x->parent->color = BLACK;
w->rchild->color = BLACK;
LeftRotate(T, x->parent);
x = T;
}
else //对称情况,如果x是其父结点的右子树
{
RBTreeNode *w = x->parent->lchild;
if(w->color == RED)
{
w->color = BLACK;
x->parent->color = RED;
RightRotate(T, x->parent);
w = x->parent->lchild;
}
if(w->lchild->color == BLACK && w->rchild->color ==BLACK)
{
w->color = RED;
x = x->parent;
}
else if(w->lchild->color == BLACK)
{
w->color = RED;
w->rchild->color = BLACK;
LeftRotate(T, w);
w = x->parent->lchild;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->lchild->color = BLACK;
RightRotate(T, x->parent);
x = T;
}
}
x->color = BLACK;
}
void RBDelete(RBTree &T, RBTreeNode *z) //在红黑树T中删除结点z
{
RBTreeNode *y;//y指向将要被删除的节点
RBTreeNode *x;//x指向将要被删除的节点的唯一儿子
if(z->lchild == nil || z->rchild ==nil)//如果z有一个子树为空的话,那么将直接删除z,即y指向z
{
y = z;
}
else
{
y = Successor(T, z);//如果z的左右子树皆不为空,则寻找z的中序后继y
}
if(y->lchild != nil)
{
x = y->lchild;
}
else
{
x = y->rchild;
}
x->parent = y->parent;//将原来y的父母设为x的父母,y即将被删除
if(y->parent == nil)
{
T = x;
}
else
{
if(y == y->parent->lchild)
{
y->parent->lchild = x;
}
else
{
y->parent->rchild = x;
}
}
if(y != z)//如果被删除的结点y不是原来将要删除的结点z,即只是用y的值来代替z的值,然后变相删除y以达到删除z的效果
{
z->elem.key = y->elem.key;
}
if( y->color == BLACK )//如果被删除的结点y的颜色为黑色,那么可能会导致树违背性质4,导致某条路径上少了一个黑色
{
RBDeleteFixup(T, x);
}
}
RBTreeNode* RBSearch(RBTree T, KeyType key)
{
if(T != nil)
{
if(key < T->elem.key)
{
RBSearch(T->lchild, key);
}
else if(key > T->elem.key)
{
RBSearch(T->rchild, key);
}
else
{
return T;
}
}
}
void MidTranverse(RBTree T)
{
if(T != NULL && T != nil)
{
MidTranverse(T->lchild);
cout<<T->elem.key<<" ";
MidTranverse(T->rchild);
}
}
int main()
{
RBTree t = NULL;
RBInsert(t,50);
RBInsert(t,40);
RBInsert(t,45);
RBInsert(t,80);
RBInsert(t,20);
RBInsert(t,60);
RBInsert(t,70);
RBInsert(t,90);
MidTranverse(t);
cout<<endl;
RBDelete(t,RBSearch(t,50));
RBDelete(t,RBSearch(t,60));
MidTranverse(t);
return 0;
}
参考:
http://blog.youkuaiyun.com/fantasywindy/article/details/5752434