红黑树

  红黑树是一种二叉排序树,是AVL树的变种, 红黑树通过一些着色法则确保没有一条路径会比其它路径长出两倍,因而达到接近平衡目的。使其比二叉查找树更有效率。

红黑树的性质如下: 

1) 每一个节点或者着红色,或者着成黑色. 
2) 根是黑色的 
3) 如果一个节点是红色的,那么它的子节点必须是黑色的. 

4) 从一个节点到一个NULL指针的每一条路径必须包含相同数目的黑色节点.  



红黑树_第1张图片

                 红黑树

红黑树的插入会出现两个红结点相邻的情况,即不平衡。

不平衡可分为以下三种情况:

case 1(俗称 “红黑红红”):

红黑树_第2张图片

这种情况下,只需改变节点的颜色,然后以新的根节点(图中为new z),作为起始节点,向上继续调整(此时new z的父节点可能为红色,因此需要继续调整)。

case 2,3 (俗称“黑红红"): 

红黑树_第3张图片

处理时,可先把case2先转化为case3,然后调整。因调整后不会出现不平衡的情况,无需继续向上调整。

 

删除节点:

  首先,我们应该想明白,删除一个节点(Z),并不等于真的删除这个节点(Z)。而是像二叉树那样,拿当前节点的次小节点(Y)来填充,如果这个次小节点(Y)是红色的,则比较好处理,只需把Y的左子树(或右子树)取代Y的位置即可;但是如果(Y)为黑色,则处理起来较麻烦。因为,删除一个黑色节点时,会造成这个黑色结点下面的若干个节点的黑色高度-1,从而不平衡。

     解决方法就是调整:想方设法把下面节点的黑色高度保持不变。

     严蔚敏版的《数据结构与算法》与算法中的调整方法类似于穷举,把周围节点的红黑情况都列出来,然后调整。这种方法很直观,比较好理解,但是因为周围节点红黑情况太多,大约需要14个if else语句才能处理。太耗费耐心,精力。

     另一种调整方法是《算法导论》里的,它把删除一个节点后造成的不平衡分为四类。为了说明方便,用X代表删除Y后补上去的结点(重色结点),w代表X的兄弟结点。

case 1: 

红黑树_第4张图片

转化为之后,X仍然是重色结点,继续进行转换。

case 2:


转化之后,再把X染为黑色即可结束。

case 3:

红黑树_第5张图片

转化之后,x仍未重色结点,需要继续进行转换。

case 4:

 红黑树_第6张图片  

 转化之后,X指向root,结束。

 也就是说,case 3、4是转化的出口,case 1、2只需先转化为case 3、4即可解决。

   

代码编写:

以前写过二叉树的程序,但是从未遇到过需要父节点的。这不,没有考虑周全就开始写代码,结果写代码的时间远远出乎意料。竟然用了大约10个小时来写红黑树。其中大部分的时间都浪费在了debug上。一遍又一遍根据输入输出,断点等找程序的bug,非常地痛苦。最后才意识到一个最大的bug:改动每一个左右节点的指向时,都要同时改变它的孩子结点的父节点指针。


代码:

 
#include<assert.h>

#include<iostream>

#include<fstream>

#include<algorithm>

#include<time.h>

#include<stack>

using namespace std;



//ºìºÚÊ÷œáµã

//E ΪœÚµãŒüÖµµÄÊýŸÝÀàÐÍ

template<class E>

class RBNode

{

public:

	E key;                      //key of the RBNode

	RBNode *left;               //pointer to the left child of this RBNode

	RBNode *right;              //pointer to the right child of this RBNode

	RBNode *parent;             //pointer to the parent child of this RBNode

	char color;                 //the RBNode's color  'B' is black, 'R' is red 

	RBNode(E k):key(k){left=right=NULL;};

	//int height; 

};

template<class E>

class RBTree

{

private:

	RBNode<E> * root;                          //root of this RBTree

	RBNode<E> * balance(RBNode<E> *  A_node);

	void RBTree<E>::leftRotate(RBNode<E> *b);   //leftRotate

	void RBTree<E>::rightRotate(RBNode<E> *d);  //rightRotate

	void  removeFix(RBNode<E> *x);           //fix the RBtree when remove a black node

	void inorder(ostream &out,RBNode<E> *p);              //output the keys in the RBTree inorder

public:

	RBTree();                               //construtor

	~RBTree();

	

    RBNode<E> * search(E key);                 //search the RBNode whose  key equals "key"

	RBNode<E> * insert(E key);                 //insert a RBNode values "key" into the RBTree 

	RBNode<E> *  remove(E key);                     //delete the RBNode whose key is "key"

	void output(ostream &out);

};



//construtor

template<class E>

 RBTree<E>::RBTree( )

{

	root=NULL;

}

 //destructor

template<class E>

 RBTree<E>::~RBTree( )

{

}

//search the RBNode whose key equals "key"

 //@param  key the key of RBNode

 //return  return the pointer to the RBNode of key,if failed,return NULL

template<class E>

RBNode<E> *RBTree<E>::search(E key)

{

	RBNode<E> *p=root;

	while(p!=NULL)

	{

		if(p->key==key)      //==

		{

			break;

		}

		else if(p->key>key)  //in left subtree

		{

			p=p->left;

		}

		else if(p->key<key)  //int right subtree

		{

			p=p->right;

		}

	}

	return p;

}

//balance the red node 

//@param node

//return the root of balanced tree

template<class E>

RBNode<E> *RBTree<E>::balance(RBNode<E> * A_node)

{

	if(A_node==root){A_node->color='B';return A_node;};

	RBNode<E> *B_node=A_node->parent;

	if(B_node->color=='B')return B_node;

	RBNode<E> *C_node=B_node->parent;

	if(C_node==NULL){ B_node->color='B';return B_node;};

	RBNode<E> *temp_root=C_node->parent;

	if(B_node==C_node->left)

	{

		if(C_node->right!=NULL&&C_node->right->color=='R')   //RBRR

		{

			C_node->right->color='B';

			C_node->color='R';

			B_node->color='B';

			return C_node;

		}

		else                                                 //BRR

		{

			if(A_node==B_node->right)             //swap A_node ,B_node

			{

				B_node->parent=A_node;

				A_node->parent=C_node;



				C_node->left=A_node;

				RBNode<E> *temp=A_node->left;

				if(A_node->left)A_node->left->parent=B_node;

				A_node->left=B_node;

				B_node->right=temp;

				

				temp=A_node;

				A_node=B_node;

				B_node=temp;

				

				

			}

			if(temp_root!=NULL)

			{

				B_node->parent=temp_root;

				if(temp_root->left==C_node)

				 	temp_root->left=B_node;

				else

					temp_root->right=B_node;

			}

			else

			{

				B_node->parent=NULL;

				root=B_node;

			}

			B_node->color='B';

			C_node->color='R';

			C_node->left=B_node->right;

			if(B_node->right)B_node->right->parent=C_node;

			B_node->right=C_node;

			C_node->parent=B_node;

			A_node->parent=B_node;

			return B_node;

		}

	}

	else if(B_node==C_node->right)

	{

		if(C_node->left!=NULL&&C_node->left->color=='R')      //RBRR

		{

			C_node->left->color='B';

			C_node->color='R';

			B_node->color='B';

			return C_node;

		}

		else

		{

			if(A_node==B_node->left)

			{

				B_node->parent=A_node;

				A_node->parent=C_node;



				C_node->right=A_node;

				RBNode<E> *temp=A_node->right;

				if(A_node->right)A_node->right->parent=B_node;

				A_node->right=B_node;

				B_node->left=temp;

				temp=A_node;

				A_node=B_node;

				B_node=temp;

				 

			}

			if(temp_root!=NULL)

			{

				B_node->parent=temp_root;

				if(temp_root->left==C_node)

				 	temp_root->left=B_node;

				else

					temp_root->right=B_node;

			}

			else

			{

				B_node->parent=NULL;

				root=B_node;

			}



			C_node->color='R';

			B_node->color='B';

			C_node->right=B_node->left;

			if(B_node->left)B_node->left->parent=C_node;

			B_node->left=C_node;

			C_node->parent=B_node;

			A_node->parent=B_node;



			return B_node;

		}

	}

	 

}

template<class E>

RBNode<E> *RBTree<E>::insert(E key)

{

	if(root==NULL)

	{

		root=new RBNode<E>(key);

		root->color='B';

		root->parent=NULL;

		return root;

	}

	 

	RBNode<E> *p=root;

	RBNode<E> *q=root;

	while(q!=NULL)

	{

		if(q->key==key)      //==

		{

			return q;        //can not insert

		}

		else if(q->key>key)  //in left subtree

		{

			p=q;

			q=q->left;

		}

		else if(q->key<key)  //int right subtree

		{

			p=q;

			q=q->right;

		}

	}

	q=new RBNode<E>(key);

	q->color='R';

	q->parent=p;

    if(q->key>p->key)

    {

		assert(p->right==NULL);

	    p->right=q;

	}

	else

	{

		assert(p->left==NULL);

	    p->left=q;

    }

	while(q->color=='R')  //balance

	{

		q=balance(q);

	}

	return q;

}

//inorder visit a tree

template<class E>

void RBTree<E>::inorder(ostream &out,RBNode<E> *p)

{

	if(p==NULL)return;

	inorder(out,p->left);

	out<<p->key<<",";

	/*if(p->parent==NULL)                     // output the black-height of the leaf node,if all the black

		p->height=1;              //is the same num,it implements the program is right,if not it is wrong  

	else

	{

			if(p->color=='B')

		    p->height=p->parent->height+1;

			else

				p->height=p->parent->height;

	}

	if(p->left==NULL&&p->right==NULL)

		cout<<"black height:"<<p->height<<endl;*/

	

	

	/*if(p->left)                       

		out<<"left "<<p->left->key;

	if(p->right)

		out<<"right "<<p->right->key;

	if(p->parent)

		out<<"parent "<<p->parent->key<<" ";*/

	inorder(out,p->right);

}

//output the RBTree

//@param  out, the output IO stream 

template<class E>

void RBTree<E>::output(ostream &out)

{

	inorder(out,root);

	out<<endl;

}

template<class E>

void RBTree<E>::leftRotate(RBNode<E> *b)

{

	RBNode<E> *d=b->right;

	if(d==NULL)return;

	RBNode<E> *temp_root=b->parent;

	RBNode<E> *c=d->left;



	b->right=c;

	if(c!=NULL)

		c->parent=b;

	d->left=b;

	b->parent=d;



	d->parent=temp_root;

	if(temp_root==NULL)

	{

		root=d;

	}

	else 

	{

		if(temp_root->left==b)

			temp_root->left=d;

		else if(temp_root->right==b)

			temp_root->right=d;

	}

	 

}

template<class E> 

void RBTree<E>::rightRotate(RBNode<E> *A)

{

	/*RBNode<E> *b=d->parent;

	RBNode<E> *c=d->left;

	d->left=c->right;

	if(c->right!=NULL)c->right->parent=d;

	c->right=d;

	d->parent=c;

	c->parent=b;

	if(b==NULL)

		root=c;

	else 

	{

		if(b->left==d)

		b->left=c;

	    else if(b->right==d)

		b->right=c;

	}

	*/



	 RBNode<E> * B;

    B = A->left;

   if (NULL == B)

        return;

   A->left = B->right;

    if (NULL != B->right)

        B->right->parent = A;

    B->parent = A->parent;

    // ÕâÑùÈýžöÅжÏÁ¬ÔÚÒ»Æð±ÜÃâÁËA->parent = NULLµÄÇé¿ö

   if (A == root)

    {

        root = B;

    }

    else if (A == A->parent->left)

    {

        A->parent->left = B;

    }

    else

    {

        A->parent->right = B;

    }

    A->parent = B;

    B->right = A;



}

template<class E>

void RBTree<E>::removeFix(RBNode<E> *x)

{

	RBNode<E> *w;

	while(x!=root&&x->color=='B')

	{

		if(x==x->parent->left)

		{

			w=x->parent->right;

			if(w==NULL)

				continue;

			//case 1

			if(w->color=='R')

			{

				x->parent->color='R';

				w->color='B';

				leftRotate(x->parent);

				w=x->parent->right;

			}

			//case 2

			if(w->left!=NULL&&w->left->color=='B'&&w->right!=NULL&&w->right->color=='B')

			{

				w->color='R';

				x=x->parent;

			}

			else

			{   //case 3

				if(w->right!=NULL&&w->right->color=='B')

				{

					w->color='R';

					w->left->color='B';

					rightRotate(w);

					w=x->parent->right;

				}

				w->color=x->parent->color;

				x->parent->color='B';

				w->right->color='B';

				leftRotate(x->parent);

				x=root;

			}

		}

		else if(x==x->parent->right) //Symmetric

		{

			w=x->parent->left;

			if(w==NULL)

				continue;

			//case 1 

			if(w->color=='R')

			{

				w->color='B';

				x->parent->color='R';

				rightRotate(x->parent);

				w=x->parent->left;

			}

			//case 2

			if(w->left!=NULL&&w->left->color=='B'&&w->right!=NULL&&w->right->color=='B')

			{

				w->color='R';

				x=x->parent;

			}

			else

			{

				if(w->left->color=='B')

				{

					w->right->color='B';

					w->color='R';

				    leftRotate(w);

					w=x->parent->left;

				}

				//case 4

				w->color=x->parent->color;

				x->parent->color='B';

				w->left->color='B';

				rightRotate(x->parent);

				x=root;

			}

		}

	}

	x->color='B';

}

//remove the node whose key equals key

//@param key,the key of the node to be removed 

//return the node was remove actually

 

template<class E>

RBNode<E> *RBTree<E>::remove(E key)

{

	RBNode<E> *z=this->search(key);     //find the node to be removed 

	if(z==NULL)return NULL;             //the node do not exist in this tree



	RBNode<E> *y;

	if(z->left==NULL||z->right==NULL)

	{

		y=z;

	}

	else

	{

		y=z->right;

		while(y->left!=NULL)

		{

			y=y->left;

		}

	}

	 

	RBNode<E> *x;

	//xÊÇyµÄ×ÓÊ÷,¿ÉÄÜΪNULL

	if(y->left!=NULL)

	{

		x=y->left;

	}

	else 

	{

		x=y->right;

	}

	if(x!=NULL)

	x->parent=y->parent;

	if(y->parent==NULL)

		root=x;

	else if(y==y->parent->left)

		y->parent->left=x;

	else if(y==y->parent->right)

		y->parent->right=x;





	if(y->key!=z->key)

		z->key=y->key;

	if(y->color=='B'&&x!=NULL) //if the actually removed node is black 

		removeFix(x); //fix to balance

	free(y);

	return root;

}



int main()

{

     RBTree<int> *rbtTree=new RBTree<int>();

	 ofstream cout("output.txt");

	 //ifstream cin("input.txt");

	 int n=50;

	 int *data=new int[n];

	 srand((unsigned int )time(0));

	 for(int i=0;i<n;)

	 {

		 data[i]=rand()%50000;

		 int j;

		 for(j=0;j<i;j++)

		 {

			 if(data[j]==data[i])

			 break;

		 }

		 if(j==i)

			 i++;

	 } 

	 //int data[]={122,328, };

	 for(int i=0;i<n;i++)

	 {

		 cout<<data[i]<<",";

	 }

	 cout<<endl;

	 for(int i=0;i<n;i++)

	 {

		  rbtTree->insert(data[i]);

	 }

	  rbtTree->output(cout);

	  //sort(data,data+n);

	  for(int i=0;i<n;i++)

	 {

		cout<<data[i]<<",";

	 }

	 cout<<endl;

	 for(int i=0;i<n;i++)

	 {

		  rbtTree->remove(data[i]);

		  rbtTree->output(cout);

	 }

	return 0;

}

参考:
http://www.cppblog.com/goodwin/archive/2011/08/08/152797.html

你可能感兴趣的:(红黑树)