RBTree


#ifndef RBTREE_H_
#define RBTREE_H_

#include <iostream>
#include <string>
using namespace std;

#define BLACK 0
#define RED 1

struct Node
{
	int key;                //节点键值
	string ID;  
	int color;              //节点颜色
	Node *left;             //左叶节点
	Node *right;            //右叶节点
	Node *parent;           //父节点
};
                 

class RBTree
{
private:
	Node *root;              //根节点            
	Node *nil;               //哨兵,颜色为BLACK
	int bHeight;             //黑高
	int nodeNum;             //节点个数
	void LeftRotate(Node *x);              //左旋转
	void RightRotate(Node *x);             //右旋转
	void InsertFixup(Node *p);             //插入节点p时维护红黑树性质
	void Transplant(Node *u, Node *v);     //用另一棵子树替换一棵子树并成为其双亲的孩子结点
	void DeleteFixup(Node *x);             //删除结点时维护红黑树性质
public:
	RBTree();
	void Destory(Node *p);          //销毁树
	Node *Minimum(Node *x);         //最小键值结点
	Node *Maximum(Node *x);         //最大键值结点
	Node *Successor(Node *x);       //后继
	Node *Predecessor(Node *x);     //前驱
	Node *Search(Node *x,int k);            //搜索树
	void Insert(Node *z);           //插入节点
	void Delete(int k);           //删除结点,该结点键值为k
	void Out(Node *p);
	void Display();
};


/*
功能:左旋转
条件:x的右孩子y不是nil
步骤:x成为y的左孩子,y的左孩子成为x的右孩子,x的左孩子和y的右孩子不变
*/
void RBTree::LeftRotate(Node *x)
{
	Node *y=x->right;
	x->right=y->left;             //修改x的右孩子
	y->left->parent=x;            //修改y的左孩子的父节点
	y->parent=x->parent;          
	if(x->parent==nil)
		root=y;
	else if(x==x->parent->left)    //x为左孩子
		x->parent->left=y;
	else                           //x为右孩子
		x->parent->right=y;
	y->left=x;
	x->parent=y;
}


/*
功能:右旋转
条件:x的左孩子不能为空
步骤:x成为y的右孩子,y的右孩子成为x的左孩子
说明:与左旋转对称
*/
void RBTree::RightRotate(Node *x)
{
	Node *y=x->left;
	x->left=y->right;
	if (y->right!=nil)
		y->right->parent=x;
	y->parent=x->parent;
	if(x->parent==nil)
		root=y;
	else if(x==x->parent->left)
		x->parent->left=y;
	else
		x->parent->right=y;
	y->right=x;
	x->parent=y;
}

/*
功能:插入节点p时维护红黑树性质
说明:p的颜色为红色,所以p的父节点不能为红色
红黑树相关性质:(2)根结点是黑色的(改变)
               (4)如果一个节点是红色的,那么他的两个子节点都是黑色的(改变)
               (5)对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点(始终成立)
*/
void RBTree::InsertFixup(Node *p)
{
	while(p->parent->color==RED)                         //p的父节点也是红色
		if(p->parent==p->parent->parent->left)            //如果p的父节点是左节点
		{
			Node *y=p->parent->parent->right;            //y为p的叔节点
			if(y->color==RED)                             //情况1:叔节点y为红色(与父节点在左或右无关)
			{
				p->parent->color=BLACK;
				y->color=BLACK;
				p->parent->parent->color=RED;
				p=p->parent->parent;
			}
			else                                   //叔结点y为黑色                          
			{
				if (p == p->parent->right)          //情况2:p的叔结点y是黑色且p是一个右孩子(包括2种情况:父节点在左和右)
				{
					p = p->parent;
					LeftRotate(p);
				}

				//Display();
				p->parent->color=BLACK;            //情况3:p的叔结点y是黑色且p是一个左孩子(方法:改变颜色做右旋)
				p->parent->parent->color=RED;
				RightRotate(p->parent->parent);
			}
		}
		else if (p->parent == p->parent->parent->right)    //如果p的父节点是右节点                        //the same as above,exchange right and left
		{
			Node *y=p->parent->parent->left;
			if(y->color==RED)
			{
				p->parent->color=BLACK;
				y->color=BLACK;
				p->parent->parent->color=RED;
				p=p->parent->parent;	
			}
			else 
			{
				if (p == p->parent->left)
				{
					p = p->parent;
					RightRotate(p);
				}

				
				p->parent->color=BLACK;
				p->parent->parent->color=RED;
				LeftRotate(p->parent->parent);
			}
		}
	root->color = BLACK;
}



/*
功能:删除节点p时维护红黑树性质
问题:(1)如果y是原来的根结点,,而y的一个红色的孩子成为新的根结点,则违反了性质2
      (2)如果x替换y后x和x-parent是红色的,则违反了性质4
	  (3)在树中移动y将导致先前包含y的任何路径上黑色结点个数少1
*/
void RBTree::DeleteFixup(Node *x)
{
	while (x != root && x->color == BLACK)
	{
		if (x == x->parent->left)
		{
			Node *w = x->parent->right;
			if (w->color == RED)                                         //情况1:x的兄弟结点是红色的
			{
				x->parent->color = RED;
				w->color = BLACK;
				LeftRotate(x->parent);
				w = x->parent->right;                  //设置新的w
			}

			else
			{
				if (w->right->color == BLACK && w->left->color == RED)               //情况2:x的兄弟结点w是黑色,而w的两个子节点都是黑色
				{
					w->color = RED;
					x->parent->color = BLACK;
					x = x->parent;
				}

				else
				{
					if (w->right->color == RED)              //情况3:x的兄弟w是黑色的,w的右孩子是黑色(w的左孩子是红色)。
					{
						w->color = BLACK;
						w->left->color = RED;
						RightRotate(w);
						w = x->parent->right;
					}
					//情况3转换为情况4
					                                         //情况4:x的兄弟w是黑色的,且w的右孩子时红色的 
					w->color = x->parent->color;
					x->parent->color = BLACK;
					w->right->color = BLACK;
					LeftRotate(x->parent);
					x = root;                   //为了终止循环
				}
			}
		}//if

		else
		{
			Node *w = x->parent->left;
			if (w->color == RED)                                         //情况1:x的兄弟结点是红色的
			{
				x->parent->color = RED;
				w->color = BLACK;
				RightRotate(x->parent);
				w = x->parent->left;                  //设置新的w
			}

			else
			{
				if (w->left->color == BLACK && w->right->color == RED)               //情况2:x的兄弟结点w是黑色,而w的两个子节点都是黑色
				{
					w->color = RED;
					//x->parent->color = BLACK;
					x = x->parent;
				}

				else
				{
					if (w->left->color == RED)              //情况3
					{
						w->color = BLACK;
						w->right->color = RED;
						LeftRotate(w);
						w = x->parent->left;
					}
					//情况3转换为情况4
					//情况4:x的兄弟w是黑色的,且w的右孩子时红色的 
					w->color = x->parent->color;
					x->parent->color = BLACK;
					w->left->color = BLACK;
					RightRotate(x->parent);
					x = root;                   //为了终止循环
				}
			}
		}//else
	}//while
	x->color = BLACK;         //如果X节点原来为红色,那么直接改为黑色
}


/*
功能:用另一棵子树替换一棵子树并成为其双亲(父节点)的孩子结点
输入参数:以v为根的子树替换以u为根的子树时,结点u的双亲变为结点v的双亲,并且最后v成为u的双亲的相应孩子
*/
void RBTree::Transplant(Node *u, Node *v)
{
	if (u->parent == nil)
		root = v;
	else if (u == u->parent->left)
		u->parent->left = v;
	else
		u->parent->right = v;
	v->parent = u->parent;
}




/*构造函数*/
RBTree::RBTree()
{
	nil=new Node;
	nil->color=BLACK;
	root=nil;
	bHeight=0;
	nodeNum=0;
}


/*销毁树,类似于析构函数,但是要手动调用*/
void RBTree::Destory(Node *p)
{
	if(p==nil)
		delete p;
	else
	{
		Destory(p->left);
		Destory(p->right);
		delete p;
	}
}


/*
功能:沿着某一结点,找到最小键值对应的结点
*/
Node *RBTree::Minimum(Node *x)
{
	while (x->left != nil)
		x = x->left;
	return x;
}


/*
功能:沿着某一结点,找到最大键值对应的结点
*/
Node *RBTree::Maximum(Node *x)
{
	while (x->right != nil)
		x = x->right;
	return x;
}


/*
功能:找到后继结点
说明:按中序遍历的次序查找后继,如果所有关键字都不同,则一个结点的后继是大于x->key的最小关键字的结点。即右子树中向左遍历,左孩子为nil的结点
*/
Node *RBTree::Successor(Node *x)
{
	if (x->right != nil)
		return Minimum(x->right);
	Node *y = x->parent;
	while (y != nil&&x == y->right)
	{
		x = y;
		y = y->parent;
	}
	return y;
}


/*
功能:找到前继结点
说明:按中序遍历的次序查找前继,如果所有关键字都不同,则一个结点的后继是大于x-<key的最大关键字的结点。
*/
Node *RBTree::Predecessor(Node *x)
{
	if (x->left != nil)
		return Maximum(x->left);
	Node *y = x->parent;
	while (y != nil&&x == y->left)
	{
		x = y;
		y = y->parent;
	}
	return y;
}





/*
功能:根据键值搜索树,返回指向找到结点的指针,找不到返回nil
输入参数:指向树根的指针x和关键字k;x的作用是迭代
*/
Node *RBTree::Search(Node *x,int k)
{
	if (x == nil || k == x->key)
		return x;
	if (k < x->key)
		return Search(x->left, k);
	else
		return Search(x->right, k);
}


/*
功能:插入一个节点
入口参数:节点p
说明:插入过程按普通二叉搜索树,调用InsertFixup()函数用来保持红黑树性质
*/
void RBTree::Insert(Node *z)
{
	Node *p=new Node;
	p=z;
	p->color = RED;
	if (root == nil)
	{
		p->parent = nil;
		root = p;
	}
		
	else
	{
		Node *x = root;
		Node *y = nil;
		while (x != nil)
		{
			y = x;                       //最后y总为x的父节点
			if (p->key<x->key)
				x = x->left;
			else
				x = x->right;
		}
		p->parent = y;                   //这样,p就是x的兄弟

		if (p->key<y->key)
			y->left = p;
		else
			y->right = p;

	}
	p->left = nil;
	p->right = nil;
	nodeNum++;
	InsertFixup(p);
}


/*
功能:删除一个结点,其键值k
入口参数:待删除的结点的键值
说明:删除后用DeleteFixup()来维护红黑树性质
*/
void RBTree::Delete(int k)
{
	Node *z = Search(root, k);
	Node *y = z;
	Node *x = nil;
	int oriColor = y->color;              //y的最初颜色
	if (z->left == nil)
	{
		x = z->right;                    //保存结点x的踪迹,最终移至结点y的原始位置上,指向y的唯一子节点或哨兵
		Transplant(z,z->right);
	}

	else if (z->right == nil)
	{
		x = z->left;
		Transplant(z,z->left);
	}
	
	else
	{
		y = Minimum(z->right);
		oriColor = y->color;
		x = y->right;                       //x为y的右孩子,不是z的
		if (y->parent != z)
		{
			Transplant(y,y->right);
			y->right = z->right;
			y->right->parent = y;
		}
		Transplant(z,y);
		y->left = z->left;
		y->left->parent = y;              //*
		y->color = z->color;              //最后把z的颜色赋给y,所以y的新位置不会出现两红情况
	}

	if (oriColor == BLACK)               //如果y是红色,当y被删除或移动时,红黑性质依然保持
		DeleteFixup(x);
}



void RBTree::Out(Node *p)
{
	if(p!=nil)
	{
		
		Out(p->left);
		cout << p->color << " " << p->ID << " " << p->key << endl;
		Out(p->right);
	}

}

void RBTree::Display()
{
	cout<<"颜色 "<<"ID "<<"key"<<endl;
	Out(root);
}
#endif

#include "RBTree.h"



int main()
{
	Node node[11]={{10,"A"},{14,"B"},{4,"C"},{12,"D"},{11,"E"},{13,"F"},{7,"G"},{16,"H"},{65,"I"},{43,"J"},{98,"K"}};
	Node node2[6] = { { 41 }, { 38 }, { 31 }, { 12 }, { 19 }, { 8 } };
	RBTree tree1;
	for (int i = 0; i < 11; i++)
	{
		tree1.Insert(node + i);
		tree1.Display();
	}
	cout << "插入后:" << endl;
	tree1.Display();
	tree1.Delete(11);
	cout << "删除后:" << endl;
	tree1.Display();
	tree1.Delete(43);
	tree1.Display();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值