您的位置:首页 > 其它

算法导论——红黑树

2018-03-18 07:47 204 查看
#include<stdio.h>
#include<iostream>
#include<stdlib.h>

using namespace std;
enum Color{RED, BLACK};
const int Length = 10;

typedef struct RB
{
int key;
RB *parent;
RB *left;
RB *right;
Color color;
}RBTreeNode, *RBTree;

RBTree NIL = NULL;

void RBInsertFix(RBTree &T, RBTree node);
void LeftRotate(RBTree &T, RBTree x);
void RightRotate(RBTree &T, RBTree x);
void RBInsert(RBTree &T, int num);
void RBTransPlant(RBTree &T, RBTree u, RBTree v);
void RBDeleteFix(RBTree &T, RBTree x);
void RBDelete(RBTree &T, RBTree Node);
void InorderWalk(RBTree T);
RBTree RBTreeMinimum(RBTree T);
void InitRBTree(RBTree &T, int num[]);
RBTree Tree_Search(RBTree T ,int k); //寻找数k是否在树中,且返回数k的地址

int main()
{
RBTree T;
int num[Length] ={12, 2, 34, 56, 26, 8, 31, 6, 20, 3};
InitRBTree(T, num);
InorderWalk(T);
printf("\n\n-----------删除操作后-------------\n");

RBDelete(T,Tree_Search(T,2));
RBDelete(T,Tree_Search(T,56));
RBDelete(T,Tree_Search(T,3));
RBDelete(T,Tree_Search(T,34));
InorderWalk(T);

}

RBTree Tree_Search(RBTree T ,int k)  //寻找数k是否在树中,且返回数k的地址
{

while(T !=NIL && T->key != k)
{
if ( k < T->key)
T=T->left;
else
T=T->right;
}

if ( T == NIL)
{
return NULL;
}

else
{
return T;
}

}

void RightRotate(RBTree &T, RBTree x)
{
RBTree y = x->left;
x->left = y->right;

if(y->right != NIL)
y->right->parent = x;

y->parent = x->parent;
if(x->parent == NIL)
T = y;
else if(x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->right = x;
x->parent = y;
}
void LeftRotate(RBTree &T, RBTree x)
{
RBTree y = x->right;
x->right = y->left;

if(y->left != NIL)
y->left->parent = x;
y->parent = x->parent;
if(x->parent == NIL)
T = y;
else if(x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}

void RBInsert(RBTree &T, RBTree node)
{
RBTree y = NIL;
RBTree x = T;
while(x != NIL)
{
y = x;
if(x->key > node->key)
x = x->left;
else
x = x->right;
}
node->parent = y;
if(y == NIL)
T = node;
else if(node->key < y->key)
y->left = node;
else
y->right = node;
RBInsertFix(T, node);
}

void RBInsertFix(RBTree &T, RBTree node)
{
RBTree y = NULL;
while(node->parent->color == RED)
{

4000
if(node->parent == node->parent->parent->left)
{
y = node->parent->parent->right;
if(y->color == RED)
{
node->parent->color = BLACK;
y->color = BLACK;
node->parent->parent->color = RED;
node = node->parent->parent;
}
else if(node == node->parent->right)
{
node = node->parent;
LeftRotate(T, node);
node->parent->color = BLACK;
node->parent->parent->color = RED;
RightRotate(T, node->parent->parent);
}
else
{
node->parent->color = BLACK;
node->parent->parent->color = RED;
RightRotate(T, node->parent->parent);
}
}
else
{
y = node->parent->parent->left;
if(y->color == RED)
{
node->parent->color = BLACK;
y->color = BLACK;
node->parent->parent->color = RED;
node = node->parent->parent;
}
else if(node == node->parent->left)
{
node = node->parent;
RightRotate(T, node);
node->parent->color = BLACK;
node->parent->parent->color = RED;
LeftRotate(T, node->parent->parent);
}
else
{
node->parent->color = BLACK;
node->parent->parent->color = RED;
LeftRotate(T, node->parent->parent);
}
}
}
T->color = BLACK;
}

void InitRBTree(RBTree &T, int num[])
{
RBTree node = NULL;
NIL = (RBTree)malloc(sizeof(RBTreeNode));
NIL->left = NIL->right = NIL->parent = NULL;
NIL->color = BLACK;
T = NIL;

for(int i = 0; i < Length; i++)
{
node = (RBTree)malloc(sizeof(RBTreeNode));
node->left = node->right = node->parent = NIL;
node->key = num[i];
node->color = RED;
RBInsert(T, node);
}
}

void RBDeleteFix(RBTree &T, RBTree x)
{
RBTree w = NULL;
while(x != T && x->color == BLACK)
{
if(x == x->parent->left)
{
w = x->parent->right;
if(w->color == RED)
{
w->color = BLACK;
x->parent->color = RED;
LeftRotate(T, x->parent);
w = x->parent->right;
}
if(w->left->color == BLACK && w->right->color == BLACK)
{
w->color = RED;
x = x->parent;
}
else if(w->right->color == BLACK)
{
w->left->color = BLACK;
w->color = RED;
RightRotate(T, w);
w = x->parent->right;
w->color = x->parent->color;
x->parent->color = BLACK;
w->right->color = BLACK;
LeftRotate(T, x->parent);
x = T;
}
else
{
w->color = x->parent->color;
x->parent->color = BLACK;
w->right->color = BLACK;
LeftRotate(T, x->parent);
x = T;
}
}
else
{
w = x->parent->left;
if(w->color == RED)
{
w->color = BLACK;
x->parent->color = RED;
RightRotate(T, x->parent);
w = x->parent->left;
}
if(w->right->color == BLACK && w->left->color == BLACK)
{
w->color = RED;
x = x->parent;
}
else if(w->left->color == BLACK)
{
w->right->color = BLACK;
w->color = RED;
LeftRotate(T, w);
w = x->parent->left;
w->color = x->parent->color;
x->parent->color = BLACK;
w->left->color = BLACK;
RightRotate(T, x->parent);
x = T;
}
else
{
w->color = x->parent->color;
x->parent->color = BLACK;
w->left->color = BLACK;
RightRotate(T, x->parent);
x = T;
}

}
}
x->color = BLACK;
}

void RBTransPlant(RBTree &T, RBTree u, RBTree v)
{
if(u->parent == NIL)
T = v;
else if(u == u->parent->left)
u->parent->left = v;
else
u->parent->right = v;

v->parent = u->parent;//对v无条件执行 即使v是代表空的哨兵NIL 与二叉排序树的不同
}

/*如果删除的结点y是红色的,则删除后的树仍然是保持红黑树的性质,因为树中各个结点的黑高度没有改变,
不存在两个相邻(父结点和子结点)的红色结点,y是红色不可能是根,所有根仍然是黑色。如果删除的结点z是黑色的,
则这个是破坏了红黑树的性质,需要调用RB_DELETE_FIXUP进行调整。从删除结点y的唯一孩子结点x或者是NIL处开始调整。
*/

RBTree RBTreeMinimum(RBTree T)
{
while(T->left != NIL)
T = T->left;
return T;
}
void RBDelete(RBTree &T, RBTree Node)
{
int precolor;
RBTree y = Node, x = NULL;
precolor = y->color;//对y也就是z的初始颜色进行记录

if(Node->left == NIL)
{
x = Node->right;//若是z没有左子树 则可以直接将右子树取代z
RBTransPlant(T, Node, Node->right);
}
else if(Node->right == NIL)
{
x = Node->left;//没有右子树 则直接用左子树取代z
RBTransPlant(T, Node, Node->left);
}
else
{//存在左右子树
y = RBTreeMinimum(Node->right);//找到Node的后继结点 即右子树中的最小值
precolor = y->color;//记录y的初始颜色
x = y->right;//因为后面的操作会将y变成z原有的颜色 所以违反性质的就是y的右孩子

if(y->parent == Node)//如果y是Node的孩子
x->parent = y;//x的父节点仍然是y
else//作为后继结点的y不是Node的孩子 而存在在其右子树中
{//将y 用y的右子树代替
RBTransPlant(T, y, y->right);
y->right = Node->right;
y->right->parent = y;
}
RBTransPlant(T, Node, y);//将Node 用y代替
y->left = Node->left;//将Node的左子树转移到y上 因为y是Node的后继结点因此可以确保大小关系正确
y->left->parent = y;
y->color = Node->color;///更改y的颜色,这样的话从y以上红黑树的性质都不会违反

//若之前的颜色是红色 则不会破坏树的性质

}
if(precolor == BLACK) ///如果y原来的颜色是黑色,那么就意味着有一个黑色结点被覆盖了,
///红黑树的性质可能会被破坏(性质4或5),需要调整
RBDeleteFix(T, x);
}

void InorderWalk(RBTree T)
{
if(T == NIL)
{
return;
}
InorderWalk(T->left);
printf("%d", T->key);
if(T->color == BLACK)
printf("-B  ");
else
printf("-R  ");
InorderWalk(T->right);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  红黑树