算法导论第13章-红黑树

   实际应用中,我们不会直接使用二叉搜索树,因为二叉搜索树的性能严重依赖于元素的插入顺序,尤其是当元素以递增的形式插入时,此时的二叉搜素树就会成为一条链表;我们在实际应用中,使用”平衡“二叉搜索树,包括AVL树,红黑树,AA树,最常用的是红黑树(其中STL中关联容器的底层实现都是使用的红黑树),可以保证最坏情况下基本动态集合操作的时间复杂度为O(lgn)


红黑树在每个节点上,增加一个颜色属性,可以是RED或BLACK,由于红黑树的性质,可以保证没有一条路径会比其他路径长出倍,因此是”近似平衡“的,但是红黑树通常能导致良好的平衡状态,经验告诉我们,红黑树的搜索平均效率与AVL树相等


红黑树的性质:
 1.每个结点或者是红色,或者是黑色;
 2.根结点是黑色
 3.每个叶结点(NULL)是黑色
 4.如果一个结点是红色的,则它的两个子结点都是黑色的
 5.对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点

红黑树的实现策略:
 增加哨兵:T.nil来代表NIL,其中T.nil是与普通结点具有相同属性的对象,所有指向NIL的指针都用指向T.nil的指针替换(主要原因是NIL无法加颜色)
 我们可以像图(a)一样,为每一个叶结点增加哨兵,这样每个NIL的父结点都有良好的定义,但是会浪费大量空间,所以我们只用一个哨兵T.nil来代表所有的NIL:所有的叶结点和根结点的父结点。

可能大家会有疑问,为什么要定义一个T.nil呢?直接用NULL来表示,我们默认为是黑色不就行了吗?STL中确实没有这个哨兵,但是,stl中没有删除操作------据我所知,T.nil的最大作用在于删除操作------它的父结点可以改变为任何一个节点,用于回溯其父结点。


在红黑树的实现中,能够改变子树高度,也就是能够使其不同于一般二叉搜索树的操作是:旋转。旋转可以改变子树的高度,维持红黑树的性质:


左旋(x,y都不是T.nil)提升y,降低x;主要是交换好各自的父子关系:

LEFT-ROTATE(T,x)
 y=x.right
 x.right=y.left
 if y.left!=T.nil
   y.left.p=x
 y.p=x.p
 if x.p==T.nil//x为根
   T.root=y
 else if x==x.p.left
   x.p.left=y
 else
   x.p.right=y
 y.left=x
 x.p=y

右旋:

RIGHT-ROTATE(T,x)
 y=x.left
 x.left=y.right
 if y.right!=T.nil
   y.right.p=x
 y.p=x.p
 if x.p=T.nil
   T.root=y
 elseif x==x.p.left
   x.p.left=y
 else
   x.p.right=y
 y.right=x
 x.p=y


插入操作:

插入操作分为两部分:插入和调整;

假设要插入的节点都为红色,那么红黑树的性质1,3,5不变,当原来的树为空时,会改变性质2;还有可能改变的性质是性质四;

我们之后进行的调整工作就是能够再次使性质2和4保持。

RB-INSERT(T,z)
 y=T.nil
 x=T.root
 while x!=T.nil
   y=x
   if z.key<x.key
     x=x.left
   else
     x=x.right

 z.p=y
 if y==T.nil
   T.root=z
 elseif z.key<y.key
   y.left=z
 else y.right=z
 //下面是比一般二叉搜索树多出来的部分
 z.left=T.nil
 z.right=T.nil
 z.color=RED
 RB-INSERT-FIXUP(T,z)//调整
调整的原则是把破坏规则的节点尽量上移,最坏情况下如果上移到根结点,只要把根结点设置成黑色,就万事大吉。
调整发生在:当插入结点的父结点是红结点时,此时必有祖父结点为黑色,叔父结点未知:

此时有六种情况,下面分析当插入结点的父结点是祖父节点的左孩子时的三种情况:

case1:叔节点为红色(插入节点为左侧插入---外插,或者为右侧插入---内插)

这时候,只要把c遍为红色,B,D变为黑色,blak-height不变,此时,唯一有可能违反性质的节点是C,所以破坏规则的节点上移了。

case2:叔节点是黑色,插入节点是右侧插入---内插:


我们将内侧插入转变为外侧插入,以插入节点的父结点A做左旋,此时令z指向B,变为外侧插入,即第三种情况

case3:叔节点是黑色,插入节点是左侧插入---外插


此时以C为支点,做右旋,然后把B变成黑色,C变成红色即可。

RB-INSERT-FIXUP(T,z)
 while z.p.color==RED
   if z.p==z.p.p.left
     y=z.p.p.right//叔父结点
	 if y.color==RED//case1
	   z.p.color=BLACK
	   y.color=BLACK
	   z.p.p.color=RED
	   z=z.p.p
	 elseif z=z.p.right//case2
	   z=z.p
	   LEFT-ROTATE(T,z)
	   //此时成为外侧插入,执行case3
	   z.p.color=BLACK
	   z.p.p.color=RED
	   RIGHT-ROTATE(T,z.p.p)
   else //插入节点的父结点为祖父节点的右孩子
     将[left]与[right]互换
 T.root.color=BLACK

对于删除操作,也分为删除和调整两部分

首先是删除操作的辅助程序-TRANSPLANT,将以u为根的子树用以v为根的子树替换,通常适用于v是u的唯一子结点时

RB-TRANSPLANT(T,u,v)
 if u.p==T.nil
   T.root=v
 elseif u==u.p.left
   u.p.left=v
 else u.p.rigth=v
 v.p=u.p

删除程序同二叉搜索树,[见二叉搜索树代码解析]

调整:

这次的焦点放在-y:从树中删除的节点或者移至树中的节点(即原来要删除节点的后继)

当y为红色时,直接删除,不违反性质;

当y为黑色时,对于y为删除节点,那么包含y的任意简单路径上黑节点少1;对于y为移动节点,同理;

这里我们采用的策略是:

令x为删除或移动y后顶替位置的元素,那么设x还有一重黑色,但是现在的问题变为:x既不是红色也不是黑色,违反性质1.


当x是其父节点的左孩子时:

case0:

当x是单重黑色,单重红色时,直接令x为黑色,则完成任务;


case1:x是双重黑色,x的兄弟节点w是红色,此时必有x父结点为黑色:


此时我们要做的是:以x的父结点B左旋,使B的颜色变为红色,w的颜色变为黑色,此时除性质1外,其他性质保持

<经过case1之后,x的兄弟节点为黑色>

case2:x是双重黑色,x的兄弟节点w是黑色,且w的两个子结点都是黑色:


此时,令w的颜色变为红色,去掉x的一重黑色,将x父结点上加上一重黑色即可,此时,唯一违反性质的节点是x的父结点。

case3:x是双重黑色,x的兄弟节点w是黑色,w的左孩子是黑色,右孩子是红色:



此时我们将w右旋,且C变为新的w,C的颜色变为黑色,D的颜色变为红色,此时转到第四种情况

case4:x是双重黑色,兄弟节点w是黑色,且w的右孩子是红色:


此时,可以去掉x的一重黑色--如图。

RB-DELETE-FIXUP
 while x!=T.root and x.color==BLACK//此时为两重黑色
  if x=x.p.left//当x为父结点的左孩子
    w=x.p.right//x的兄弟节点
	if w.color==RED//case1
	  w.color=BLACK
	  x.p.color=RED
	  LEFT-ROTATE(T,x.p)
	  w=x.p.right
	if w.left.color==BLACK and w.right.color=BLACK//case2
	  w.color=RED
	  x=x.p
	elseif w.right.color==BLACK//case3
	  w.left.color=BLACK
	  w.color=RED
	  RIGHT-ROTATE(T,w)
	  w=x.p.right
	 //case4
	 w.color=x.p.color
	 x.p.color=BLACK
	 w.right.color=BLACK
	 LEFT-ROTATE(T,x.p)
	 x=T.root
  else 
     left与right互换
 x.color=bBLACK//case0
	  
    

下面附一份STL版的红黑树,简单版的红黑树把二叉搜索树扩展一下即可得到:

//下面使用stl版本的红黑树,简单版的红黑树跟二叉搜索树基本相同,除了插入和删除稍麻烦外。
#include"myconstruct.h"
#include"myiterator.h"
#include"mymemory.h"
#include<utility>
//表示颜色
typedef bool _rb_tree_color_type;
const _rb_tree_color_type _rb_tree_red=false;//红色为0
const _rb_tree_color_type _rb_tree_black=true;//黑色为1
//节点结构
template<typename Value>
struct _rb_tree_node
{
	typedef _rb_tree_color_type color_type;
	typedef _rb_tree_node<Value> node_type;
	
	color_type color;
	Value value_field;
	node_type* parent;
	node_type* left;
	node_type* right;

	static node_type* minimum(node_type* x)
	{
		while(x->left!=0) x=x->left;
		return x;
	}
	static node_type* maximum(node_type* x)
	{
		while(x->right!=0) x=x->right;
		return x;
	}
};

//迭代器设计:
template<typename Value,typename Ref,typename Ptr>
struct _rb_tree_iterator
{
	typedef bidirectional_iterator_tag iterator_category;
	typedef size_t       difference_type;
	typedef _rb_tree_node<Value>  node_type;
	typedef Value  value_type;
	typedef Ref reference;
	typedef Ptr pointer;
	typedef _rb_tree_iterator<Value,Value&,Value*>  iterator;
	typedef _rb_tree_iterator<Value,const Value&,const Value*> const_iterator;
	typedef _rb_tree_iterator<Value,Ref,Ptr>  self;

	node_type* node;//与容器的联系

	_rb_tree_iterator(){}
	_rb_tree_iterator(node_type* x){node=x;}
	_rb_tree_iterator(const iterator& it){node=it.node;}

	reference operator*() const {return node->value_field;}
	pointer   operator->() const{return &(operator*());}

	self& operator++(){increment();return *this;}
	self  operator++(int){self tmp=*this;increment();return tmp;}

	self& operator--(){decrement();return *this;}
	self   operator--(int){self tmp=*this;decrement();return tmp;}

	bool operator== (const self& x)const{return x.node==node;}
	bool operator!=(const self& x)const{return x.node!=node;}
private://辅助程序
	void increment();//后继
	void decrement();//前驱
};
//-------------------------------------------------------------------------------------------
/*返回中序遍历时,x的后继,其中二叉搜索树的结构允许我们不通过任何关键字的比较获得O(h):
 *case1:如果x的右子树非空,那么后继y是x右子树的最小元素
 *case2:如果x的右子树为空:
 *          case1’:如果x是父结点的左孩子,那么x的后继为父结点
 *          case2’:如果x是父结点y的右孩子,那么寻找这样一个节点z,使x,y所在的子树为z的左子树
 */
template<typename Value,typename Ref,typename Ptr>
void _rb_tree_iterator<Value,Ref,Ptr>::increment()
{
	if(node->right!=0){//case1
		node=node_type::minimum(node->right);
	}else{//case2
		//case1':
		node_type* y= node->parent;
		//case2':
		while(node==y->right){
			node=y;
			y=y->parent;
		}
		if(node->right!=y)
			node=y;
	}
}
//----------------------------------------------------------------------------------------
/*返回中序遍历时,x的前驱:O(h)
 *case1:x有左子树,那么x的前驱是x左子树的最大值;
 *case2:x无左子树
 *         case1’:x是其父结点y的右孩子,那么前驱为y
 *         case2’:x是其父结点y的左孩子,寻找祖先z,使x,y所在子树是z的右子树
 */
template<typename Value,typename Ref,typename Ptr>
void _rb_tree_iterator<Value,Ref,Ptr>::decrement()
{
	if(node->color==_rb_tree_red&&node->parent->parent==node)//header
		node=node->right;
	else if(node->left!=0){//case1
		node=node_type::maximum(node->left);
	}else{//case2
		//case1':
		node_type* y=node->parent;
		//case2':
		while(node==y->left){
			node=y;
			y=y->parent;
		}
		node=y;
	}
}
//----------------------------------------------------------------------------------------------
//红黑树
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
	typename Alloc=alloc>
	class rb_tree
	{
	protected:
		typedef void* void_pointer;
		typedef _rb_tree_node<Value> node_type;
		typedef simple_alloc<node_type,Alloc> rb_tree_node_allocator;
		typedef _rb_tree_color_type color_type;
	public:
		typedef Key  key_type;
		typedef Value value_type;
		typedef value_type* pointer;
		typedef const value_type* const_pointer;
		typedef value_type&  reference;
		typedef const value_type& const_reference;
		typedef size_t size_type;
		typedef size_t  difference_type;

		typedef _rb_tree_iterator<value_type,reference,pointer> iterator;

	protected://内存管理
		//配置一个节点
		node_type* get_node(){return rb_tree_node_allocator::allocate();}
		//释放一个节点
		void           put_node(node_type* p){rb_tree_node_allocator::deallocate(p);}
		node_type* create_node(const value_type& x){node_type* tmp=get_node();
		construct(&tmp->value_field,x);
		return tmp;
		//可以直接使用new,不过需要节点定义构造函数
		}
		node_type* clone_node(node_type* x);//复制一个节点
		void destroy_node(node_type* p){destroy(&p->value_field);//析构内容
		put_node(p);//可以直接使用delete,但是需要定义析构函数
		}
		
	protected:
		size_type node_count;
		node_type* header;//红色,技巧性实现
		Compare key_compare;//函数对象,用于比较

		node_type*& root() const{return header->parent;}
		node_type*& leftmost() const{return header->left;}
		node_type*& rightmost()const{return header->right;}
		//用于取得节点的值
		static node_type*& left(node_type* x){return x->left;}
		static node_type*& right(node_type* x){return x->right;}
		static node_type*& parent(node_type* x){return x->parent;}
		static reference   value(node_type* x){return x->value_field;}
		static const Key& key(node_type* x){return KeyOfValue()(value(x));}
		static color_type& color(node_type* x){return x->color;}
		
	private:
		iterator _insert(node_type* x,node_type* y,const value_type& v);
		void init();
		void clear();

	public://构造和析构
		rb_tree(const Compare& comp=Compare())
			:node_count(0),key_compare(comp){init();}
		~rb_tree(){clear();put_node(header);}
		rb_tree<Key,Value,KeyOfValue,Compare,Alloc>&
			operator=(const rb_tree<Key,Value,KeyOfValue,Compare,Alloc>& x);
	public:
		Compare key_comp() const{return key_compare;}
		iterator  begin(){return leftmost();}//红黑树的最小元素
		iterator end(){return header;}//header作为终点
		bool empty()const{return node_count==0;}
		size_type size() const{return node_count;}
		size_type max_size() const{return size_type(-1);}//?
	public:
		//不允许节点值重复
		std::pair<iterator,bool>  insert_unique(const value_type& x);
		//允许节点值重复
		iterator insert_equal(const value_type& x);
		iterator find(const Key& k);
	};
//----------------------------------------------------------------------------------------
	
    template<typename Key,typename Value,typename KeyOfValue,typename Compare,
	typename Alloc>
	typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::node_type*
	rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::clone_node(node_type* x)
	{
		node_type tmp=create_node(x->value_field);
		tmp->color=x->color;
		tmp->left=0;
		tmp->right=0;
		return tmp;
	}
//----------------------------------------------------------------------------------------------
	template<typename Key,typename Value,typename KeyOfValue,typename Compare,
	typename Alloc>
	void  rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::init()
	 {//header左右子结点指向自己
		 header=get_node();
		 color(header)=_rb_tree_red;
		 root()=0;
		 leftmost()=header;
		 rightmost()=header;
	}
//----------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
	typename Alloc>
typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::insert_equal(const Value& v)
{
	node_type* y=header;
	node_type* x=root();
	while(x!=0){//从根节点开始
		y=x;
		x=key_compare(KeyOfValue()(v),key(x))?left(x):right(x);
		//遇大往左走,遇小于等于往右走
	}
	return _insert(x,y,v);//y为插入点的父结点,x为插入点
}
//---------------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
	typename Alloc>
std::pair<typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator,bool>
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::insert_unique(const Value& v)
{
	node_type* y=header;
	node_type* x=root();
	bool comp=true;
	while(x!=0){
		y=x;
		comp=key_compare(KeyOfValue()(v),key(x));
		x=comp?left(x):right(x);
	}

	iterator j=iterator(y);
	if(comp){//离开while时,comp为真,插于左侧
		if(j==begin())//如果插入点父结点为最左节点
			return std::pair<iterator,bool>(_insert(x,y,v),true);
		else
			--j;
	}
	if(key_compare(key(j.node),KeyOfValue()(v)))//新键值不与既有节点值重复
		return std::pair<iterator,bool>(_insert(x,y,v),true);

	//至此,则重复
	return std::pair<iterator,bool>(j,false);
}
//------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
	typename Alloc>
typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::_insert(node_type* x,node_type* y,
const Value& v)
{
	node_type* x_copy=x;
	node_type* y_copy=y;
	node_type* z;

	if(y==header||x!=0||key_compare(KeyOfValue()(v),key(y))){
		z=create_node(v);
		left(y)=z;
		if(y==header){
			root()=z;
			rightmost()=z;
		}else if(y==leftmost()){
			leftmost()=z;
		}
	}else{
		z=create_node(v);
		right(y)=z;
		if(y==rightmost()){
			rightmost()=z;
		}
	}
		parent(z)=y;
		left(z)=0;
		right(z)=0;
		z->color=_rb_tree_red;
		_rb_insert_fixup(z,header->parent);
		++node_count;
		return iterator(z);
}
//--------------------------------------------------------------------------------------------
template<typename Key,typename Value,typename KeyOfValue,typename Compare,
	typename Alloc>
typename rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::iterator
rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::find(const Key& k)
{
	node_type* y=header;
	node_type* x=root();
	while(x!=0){
		if(!key_compare(key(x),k))//x大于k
			y=x,x=left(x);
		else
			x=right(x);
	}
	iterator j=iterator(y);
	return (j==end()||key_compare(k,key(j.node)))?end():j;
}
//------------------------------------------------------------------------------------------

template<typename Key,typename Value,typename KeyOfValue,typename Compare,
	typename Alloc>
	void rb_tree<Key,Value,KeyOfValue,Compare,Alloc>::clear()
{
	for(iterator it=begin(),next=++it;it!=end();++next){
		destroy_node(it.node);
		it=next;
	}
}
//-----------------------------------------------------------------------------------------
//全局函数1--左旋
template<typename Value>
void _rb_left_rotate(_rb_tree_node<Value>* x,_rb_tree_node<Value>*&  root)
{
	_rb_tree_node<Value>* y=x->right;
	x->right=y->left;
	if(y->left!=0){
		y->left->parent=x;
	}
	y->parent=x->parent;
	if(x==root)
		root=y;
	else if(x==x->parent->left){
		x->parent->left=y;
	}else
		x->parent->right=y;
	y->left=x;
	x->parent=y;
}
//全局函数2-右旋
template<typename Value>
void _rb_right_rotate(_rb_tree_node<Value>* x,_rb_tree_node<Value>*&  root)
{
	_rb_tree_node<Value>* y=x->left;
	x->left=y->right;
	if(y->right!=0)
		y->right->parent=x;
	y->parent=x->parent;

	if(x==root)
		root=y;
	else if(x==x->parent->right)
		x->parent->right=y;
	else 
		x->parent->left=y;
	y->right=x;
	x->parent=y;
}
//----------------------------------------------------------------------------------------
//全局函数三
template<typename Value>
void _rb_insert_fixup(_rb_tree_node<Value>* x,_rb_tree_node<Value>*&  root)
{
	while(x!=root && x->parent->color==_rb_tree_red){
		if(x->parent==x->parent->parent->left){
			_rb_tree_node<Value>* y=x->parent->parent->right;//y为x的叔父结点
			if(y&&y->color==_rb_tree_red){//case1
				x->parent->color=_rb_tree_black;
				y->color=_rb_tree_black;
				x->parent->parent->color=_rb_tree_red;
				x=x->parent->parent;
			}else{
				if(x==x->parent->right){//case2
					x=x->parent;
					_rb_left_rotate(x,root);
				}
				//case3
				x->parent->color=_rb_tree_black;
				x->parent->parent->color=_rb_tree_red;
				_rb_right_rotate(x->parent->parent,root);
			}
		}
		else{//对称的三种情况
			_rb_tree_node<Value>* y=x->parent->parent->left;
			if(y&&y->color==_rb_tree_red){//case1
				x->parent->color=_rb_tree_black;
				y->color=_rb_tree_black;
				x->parent->parent->color=_rb_tree_red;
				x=x->parent->parent;
			}else{
				if(x==x->parent->left){//case2
					x=x->parent;
					_rb_right_rotate(x,root);
				}
				//case3
				x->parent->color=_rb_tree_black;
				x->parent->parent->color=_rb_tree_red;
				_rb_left_rotate(x->parent->parent,root);
			}
		}
	}
	root->color=_rb_tree_black;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值