[算法导论]红黑树

#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)
	{
		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);
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值