用c语言实现红黑树(依据算法导论上的方法)

/*************************************************************************
    > File Name: RBT.h
    > Author: TimeFly
    > Mail: fightllz1993@163.com 
    > Created Time: 2014年08月06日 星期三 20时27分00秒
 ************************************************************************/


#ifndef RBT_H
#define RBT_H


#include <stdio.h>
#include <stdlib.h>
#include <string.h>




typedef char* ElemType;
#define ELEMTACITLY NULL //通配类型的默认值


typedef int Color;
#define RED 1
#define BLACK -1


typedef int bool;
#define true 1
#define false 0


typedef struct RBNode
{
Color color;
ElemType data;
struct RBNode *parent
struct RBNode *left;
struct RBNode *right;
}RBNode;


typedef struct RBTree
{
RBNode *Root;
RBNode *NIL;
int NodeSize;
}RBTree;


/***********************所有的函数声明**********************************/
RBTree* CreativeRBTree();
void Left-Rotate(RBTree* T,RBNode* x);
void Right-Rotate(RBTree* T,RBNode* x);
void RB_Insert(RBTree* ,RBNode* x);
bool RBNode_Less(RBNode *RBN_a,RBNode *RBN_b);
void RB_Insert_Fixup(RBTree* T,RBNode* x);


void RB_Trans_Plant(RBTree *T,RBNode *u,RBNode *v);
RBNode* RB_Tree_Min(RBTree *T,RBNode *z);
void RB_Destroy_Node(RBNode *z);
void RB_Destroy_Child_Tree(RBNode *T,RBNode *z);


void RB_Delete_Node(RBTree *T,RBNode *z);
void RB_Delete_Fixup(RBTree *T,RBNode *z);
/***********************************************************************/


//创建一颗空的红黑树
RBTree* CreativeRBTree()
{
RBTree* T = (RBTree*)malloc(sizeof(RBTree));
assert(T != NULL);
T->NIL = (RBNode*)malloc(sizeof(RBNode));
assert(T->NIL != NULL);
T->NIL->color = BLACK;
T->NIL->data = ELEMTACITLY;
T->NIL->parent = NULL;
T->NIL->left = NULL;
T->NIL->right = NULL;

T->Root = T->NIL;
return T;
}


//左旋转
void Left_Rotate(RBTree *T,RBNode *x)
{
if(x->right == T->NIL)
{
printf("x have not a right child can not be left-rotate\n");
exit(1);
}




RBNode *y = x->right;
x->right = y->left;
if(y->left != T->NIL)
{
y->left->parent = x;
}//到这一步搞定x的右孩子的左孩子

y->parent = x->parent;
if(x->parent == T->NIL)//防止x是根节点
{
T->Root = y;
}
else if(x->parent->right = x)
{
x->parent->right = y;
}
else
{
x->parent->left = y;
}//到这一步搞定x的父节点


y->left = x;
x->parent = y;
}


//右旋转
void Right_Rotate(RBTree *T,RBNode *x)
{
if(x->left == T->NIL)
{
printf("x have not a left child can not be right-rotate\n");
exit(1);
}


RBNode *y = x->left;
x->left = y->right;
if(y->right != T->NIL)
{
y->right->parent = x;
}//搞定x的左孩子的右孩子


y->parent = x->parent;
if(x->parent == T->NIL)
{
T->Root = y;
}//防止原本的x是根节点


else if(x->parent->right == x)
{
x->parent->right = y;
}
else
{
x->parent->left = y;
}//到这里把x的父节点搞定了


y->right = x;
x->parent = y;
}


//为了通用性,对于具体的红黑树,使用不同的比较函数
bool RBNode_Less(RBNode *RBN_a,RBNode *RBN_b)
{
return strcmp(RBN_a->data,RBN_b->data) < 0;
}


void RB_Insert(RBTree *T,RBNode *x,bool less(RBNode*,RBNode*));
{
RBNode *par = T->NIL;
RBNode *Temp = T->Root;


while(Temp != T->NIL)
{
par = Temp;
if(less(x,Temp))
{
Temp = Temp->left;
}
else
{
Temp = Temp->right;
}
}

x->parent = par;
if(x->parent == T->NIL)
{
T->Root = x;
}
else if(less(x,par))
{
par->left = x;
}
else
{
par->right = x;
}


x->left = T->NIL;
x->right = T->NIL;
x->color = RED;


//上面这些都是最基本的插入,很简单,唯一要注意的是,当树是空树的情况。

//这个RB_Insert_Fixup才是重头戏
RB_Insert_Fixup(T,x);
}


//插入节点成功后,调用该函数,保持红黑树性质不变
void RB_Insert_Fixup(RBTree *T,RBNode *x)
{
RBNode *uncle = NULL;//这个是父节点的兄弟节点,称呼它位叔叔节点


while(x->parent->color == RED)//如果父节点不是红节点,当然就没那么多事情了。
{
if(x->parent == x->parent->parent->left)
{
uncle = x->parent->parent->right;
if(uncle->color == RED)//这里处理的是情况1
{
x->parent->color = BLACK;
uncle->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
}
else
{
if(x == x->parent->right)//在情况2的条件下,把情况2转化为情况3
{
x = x->parent;
Left_Rotate(T,x);
}
//然后下面三条处理情况3
x->parent->color = BLACK;
x->parent->parent->color = RED;
Right_Rotate(T,x);
}
}
else //这个else和上面的仅仅是方向不同,其余的一样
{
uncle = x->parent->parent->left;
if(uncle->color == RED)
{
x->parent->color = BLACK;
uncle->color = BLACK;
x->parent->parent = RED;
x = x->parent->parent;
}
else
{
if(x == x->parent->left)
{
x = x->parent;
Right_Rotate(T,x);
}
x->parent->color = BLACK;
x->parent->parent->color = RED;
Left_Rotate(T,x);
}
}
}


//如果是情况3退出循环,当然什么也不必做,但是如果是情况1退出的循环,就存在根节点被着色的情况,所以添加该语句,不管以什么情况结尾都不会错了。
T->Root->color = BLACK;
}


//找寻从该节点开始最左端的节点
RBNode *RB_Tree_Min(RBTree *T,RBNode *z)
{
RBNode *Temp = z;
while(Temp->left != T->NIL)
{
Temp = Temp->left;
}
return Temp;
}


//把树中的节点u用节点v替换,但是这个函数不提供释放空间的功能
void RB_Trans_Plant(RBTree *T,RBNode *u,RBNode *v)
{
if(u->parent == T->Root)
{
T->Root = v;
}
else if(u->parent->right == u)
{
u->parent->right = v;
}
else
{
u->parent->left = v;
}
v->parent = u->parent;
}


//销毁一个节点,并释放其占用的空间
void RB_Destroy_Node(RBNode *z)
{
free(z->data);
free(z);
}


//销毁树T上从z节点开始所形成的子树
void RB_Destroy_Child_Tree(RBTree *T,RBNode *z)
{
if(z->left != T->NIL)
{
RB_Destroy_Child_Tree(T,z->left);
}
if(z->right != T->NIL)
{
RB_Destroy_Child_Tree(T,z->right);
}
RB_Destroy_Node(z);
}


//删除树T上的节点z,并且释放节点z的空间
void RB_Delete_Node(RBTree *T,RBNode *z)
{
RBNode *des = z;
Color origin_color = des->color;
RBNode *replace = NULL;

if(z->left == T->NIL)
{
replace = z->right;
RB_Trans_Plant(T,z,replace);
}
else if(z->right == T->NIL)
{
replace = z->left;
RB_Trans_Plant(T,z,replace);
}
else
{
des = RB_Tree_Min(T,z->right);
origin_color = des->color;
replace = des->right;


if(des->parent == z)
{
replace->parent = des;
}
else
{
RB_Trans_Plant(T,des,replace);
des->right = z->right;
des->right->parent->des;
}
RB_Trans_Plant(T,z,des);
des->left = z->left;
des->left->parent->des;
des.color = z.color;
}


if(origin_color == BLACK)
{
RB_Delete_Fixup(T,replace);
}


RB_Destroy_Node(z);


T->NIL->parent = NULL;//这句是我擅自添加的,与《算法导论》不同,因为在删除过程中NIL的parent节点可能会被修改,因为这是在特殊情况下需要使用的,在修改过后,不去修改回来,虽然不会影响到算法,但是我觉得在用完后还是纠正回指向空指针,比较好。
}


//删除后,调用该函数保存红黑树性质不变
void RB_Delete_Fixup(RBTree *T,RBNode *z)
{
RBNode *Temp = z;
RBNode *Brother = NULL;
while(Temp != T->Root && Temp == BLACK)
{
if(Temp == Temp->parent->left)
{
Brother = Temp->parent->right;


//case 1
if(Brother->color == RED)
{
Brother->color = BLACK;
Temp->parent->color = RED;
Left_Rotate(T,Temp_>parent);
Brother = Temp->parent->right;
}

//case 2
if(Brother->left == BLACK && Brother->right == BLACK)
{
Brother->color = RED;
Temp = Temp->parent;
}
else 
{
//case 3
if(Brother->right->color == BLACK)
{
Brother->left->color = BLACK;
Brother->color = RED;
Right_Rotate(T,Brother);
Brother = Temp->parent->right;
}


//case 4
Brother->color = Temp->parent->color;
Temp->parent->color = BLACK;
Brother->right->color = BLACK;
Left_Rotate(T,Temp->parent);
Temp = T->Root;
}
}

else
{
Brother = Temp->parent->left;


//case 1
if(Brother->color == RED)
{
Brother->color = BLACK;
Temp->parent->color = RED;
Right_Rotate(T,Temp->parent);
Brother = Temp->parent->left;
}


//case 2
if(Brother->right == BLACK && Brother->left == BLACK)
{
Brother->color = RED;
Temp = Temp->parent;
}
else
{
//case 3
if(Brother->left->color == BLACK)
{
Brother->right->color = BLACK;
Brother->color = RED;
Left_Rotate(T,Brother);
Brother = Temp->parent->left;
}


//case 4
Brother->color = Temp->parent->color;
Temp->parent->color = BLACK;
Brother->left->color = BLACK;
Right_Rotate(T,Brother);
Temp = T->Root;
}
}
}
Temp->color = BLACK;
}


void RB_Destroy_Tree(RBTree *T)
{
RB_Destroy_Child_Tree(T,T->Root);
free(T->NIL);
}


#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值