红黑树C++完整源码

5 篇文章 0 订阅
1 篇文章 0 订阅
// RBTree.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

template<typename T>
class RB_Tree
{
	class RB_Node;
	enum Color {BLACK,RED};
public:
	RB_Tree();
	bool Insert(T data);
	bool Insert(RB_Node &node);
	bool Delete(T data);
	bool Delete(RB_Node *node);

	RB_Node* FindData(T data)
	{
		RB_Node *p=pRoot;
		RB_Node *pFound=NULL;
		while(p!=pNil)
			if(data<p->data)
				p=p->lChild;
			else if(data>p->data)
				p=p->rChild;
			else{
				pFound=p;
				break;
			}
			return pFound;
	}

	class RB_Node{
	public:
		RB_Node():lChild(Children[0]),rChild(Children[1])
		{
			parent=NULL;
			Children[0]=Children[1]=NULL;
		}

		// To force two pointers to be together. 
                  // For later use of "lChild+1" in delete operation
		RB_Node *Children[2];
		(RB_Node *)& lChild;
		(RB_Node *)& rChild;
		RB_Node *parent;
		T data;
		Color color;
	};

private:
	void leftRotate(RB_Node *const x);
	void rightRotate(RB_Node *const x);
	void InsertFixup(RB_Node *x);
	void DeleteFixup(RB_Node *x);
	void Free(RB_Node *x);

	typedef void (RB_Tree<T>::*RotateFunc)(RB_Node *const );
	RotateFunc pRotates[2];

	RB_Node nil;
	RB_Node *pRoot,*pNil;
};

enum Twist {LR=0,RL=1,LL=2,RR=3};

template<typename T>
RB_Tree<T>::RB_Tree()
{
	pRotates[0]=&RB_Tree::leftRotate;
	pRotates[1]=&RB_Tree::rightRotate;

	//nil initialization 
	pNil=new RB_Node;
	pNil->color=BLACK;
	pRoot=pNil;

	//pNil's children and points are useless
	//pNil's parent is useful in deleting fixup.
	pNil->lChild=pNil->rChild=pNil->parent=NULL;
}

template<typename T>
void RB_Tree<T>::leftRotate(RB_Node *const x)
{
	RB_Node *y=x->rChild;

	//This case won't be happened when the function used inside the class
	if(pNil==y)
		return;

	x->rChild=y->lChild;
	if(pNil!=y->lChild)
		y->lChild->parent=x;

	y->parent=x->parent;
	if(pNil==x->parent)
		pRoot=y;
	else if(x->parent->lChild==x)
		x->parent->lChild=y;
	else
		x->parent->rChild=y;

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

template<typename T>
void RB_Tree<T>::rightRotate(RB_Node *const y)
{
	RB_Node *x=y->lChild;

	//This case won't be happened when the function used inside the class
	if(pNil==x)
		return;

	y->lChild=x->rChild;
	if(pNil!=x->rChild)
		x->rChild->parent=y;

	x->parent=y->parent;
	if(pNil==y->parent)
		pRoot=x;
	else if(y->parent->lChild==y)
		y->parent->lChild=x;
	else 
		y->parent->rChild=x;

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

template<typename T>
bool RB_Tree<T>::Insert(T data)
{
	bool bRet;
	RB_Node *pNode;
	pNode=new RB_Node;
	pNode->data=data;
	bRet=Insert(*pNode);
	return bRet;
}

template<typename T>
bool RB_Tree<T>::Insert(RB_Node &node)
{
	RB_Node *p,*pre;

	pre=pNil;
	p=pRoot;
	while(p!=pNil){
		pre=p;
		if(node.data<p->data)
			p=p->lChild;
		else if(node.data==p->data){
			printf("Data already exited.\n");
			return false;
		}
		else
			p=p->rChild;
	}

	node.parent=pre;
	node.lChild=node.rChild=pNil;
	node.color=RED;

	if(pre==pNil)
		pRoot=&node;
	else if(node.data<pre->data)
		pre->lChild=&node;
	else
		pre->rChild=&node;
	//test
	printf("data %2d has been added in case  ",node.data);
	InsertFixup(&node);
	return true;
}

template<typename T>
void RB_Tree<T>::InsertFixup(RB_Node *x)
{
	while(1){
		//case 1
		if(x==pRoot){
			x->color=BLACK;
			printf("1\n");
			return;
		}
		//case 2
		else if(x->parent->color==BLACK){
						printf("2\n");
			return;
		}

		//case 3 : parent and uncle both are red
		if(x->parent->parent->lChild->color==x->parent->parent->rChild->color){
			x->parent->parent->lChild->color=BLACK; 
			x->parent->parent->rChild->color=BLACK; 
			x->parent->parent->color=RED;
			x=x->parent->parent;
			printf("3");

		}
		//case 4:uncle node is black
		else{
			Twist twist;
			//case 4.1: uncle node is grandparent node's right node
			if(x->parent->parent->lChild->color==RED){
				if(x->parent->lChild->color==RED)
					twist=LL;
				else
					twist=LR;
			}
			else if(x->parent->lChild->color==RED)
				twist=RL;
			else
				twist=RR;

			/* enum value
			LR : 0		RL : 1		LL : 2		RR : 3
			*/
			if(twist==LR||twist==RL){
				x=x->parent;
				(this->*pRotates[twist])(x);
			}
			printf("4(%d)\n",twist);

			x=x->parent->parent;
			int opTwist=1-twist%2;
			(this->*pRotates[opTwist])(x);

			x->color=RED;
			x->parent->color=BLACK;
			return;
		}
	}
}

template<typename T>
bool RB_Tree<T>::Delete(RB_Node *p)
{
	RB_Node *del,*pre,**pParentToDel,*successor;

	if(pNil==p){
		printf("Nil can't be deleted \n");
		return false;
	}

	if(pNil==p->parent)
		pParentToDel=&pRoot;
	else if(p->parent->lChild==p)
		pParentToDel=&(p->parent->lChild);
	else
		pParentToDel=&(p->parent->rChild);

	if(pNil==p->lChild){
		del=p;
		p=p->rChild;
		p->parent=del->parent;
		*pParentToDel=p;
	}
	else if(pNil==p->rChild){
		del=p;
		p=p->lChild;
		p->parent=del->parent;
		*pParentToDel=p;
	}
	else{
		pre=p;
		del=p->lChild;

		while(del->rChild!=pNil){
			pre=del;
			del=del->rChild;
		}
		p->data=del->data;

		successor=del->lChild;
		if(del==pre->lChild)
			pre->lChild=successor;	
		else
			pre->rChild=successor;
		successor->parent=pre;
		p=successor;
	}

	if(del->color==BLACK)
		DeleteFixup(p);
	Free(del);
	return true;
}

template<typename T>
bool RB_Tree<T>::Delete(T data)
{
	RB_Node *pFound=NULL;
	bool bRet;
	pFound=FindData(data);
	if(NULL==pFound)
		return false;
	printf("%d has been deleted by ",data);
	bRet=Delete(pFound);
	cout<<endl;
	return bRet;
}

template<typename T>
void RB_Tree<T>::DeleteFixup(RB_Node *x)
{
	RB_Node *brother;
	while(x!=pRoot&&x->color==BLACK)
	{
		int direction,opDirection;
		if(x==x->parent->lChild)
			direction=0;
		else
			direction=1;
		opDirection=1-direction;

		brother=x->parent->Children[opDirection]; // <==> brother=*(&(x->parent->lChild)+opDirection);

		//case 1:Parent's black and brother's red. 
		//Rotate brother up to make parent red to enter case 2, 3, 4. 
		if(brother->color==RED){
			brother->color=BLACK;
			brother->parent->color=RED;
			(this->*pRotates[direction])(x->parent);
			brother=x->parent->Children[opDirection];
			printf("1");
		}
		//case 2;brother's black and brother's children are both Black
		//mark brother to red. Then the problem of balance is lifted up to parent
		if(brother->lChild->color==BLACK&&brother->rChild->color==BLACK){
			brother->color=RED;
			x=x->parent;
			printf("2");
		}
		else{
			//case 3: Brother's son closer to me is red,the one distanter to me is black 
			//Rotate to enter case 4
			if(brother->Children[opDirection]->color==BLACK){
				(this->*pRotates[opDirection])(brother);
				brother->color=RED;
				brother=brother->parent;
				brother->color=BLACK;
				cout<<3;
			}
			//case 4:brother's son distanter to me is red:we can rotate 
                           //brother and this son up and make the son black to balance the whole tree.
			brother->color=x->parent->color;
			x->parent->color=BLACK;
			(this->*pRotates[direction])(x->parent);
			brother->Children[opDirection]->color=BLACK;
			//to quite
			x=pRoot;
			cout<<4;
		}	
	}
	x->color=BLACK;
}

template<typename T>
void RB_Tree<T>::Free(RB_Node *x)
{
	delete x;
}

int _tmain(int argc, _TCHAR* argv[])
{
	RB_Tree<int> rb_tree;

	int times=100;
	for(int i=0;i<times;++i){
		rb_tree.Insert(-i);
		rb_tree.Insert(i);

	}

	for(int i=0;i>-times;--i)
		rb_tree.Delete(i);

	return 0;
}


 


这是本人写的实现红黑树的源码。

红黑树的实现原理具体请参见《算法导论》和v_JULY_v大神写的关于红黑树的专题:http://blog.csdn.net/v_july_v/article/category/774945

本代码与其他的红黑树代码最大的不同就是,用到了类的成员函数指针来减少代码冗余:在插入和删除节点后,都要对红黑树进行调节。而根据被插入或删除点时左子节点还是右子节点要进行分情况编写代码,而这两部分的代码是十分雷同的。所以我在源码中用到成员函数指针等技术来消除这种冗余。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值