红黑树

/* 
性质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.csdn.net/fantasywindy/article/details/5752434
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值