红黑树

  红黑树>

    在之前实现了AVL树,其实红黑树和AVL树都是高效且平衡的二叉搜索树,增删查改的时间复杂度都是O(lg N).但是在实际应用中红黑树的应用最多,比如C++STL库--map/set,java库,Linux内核以及其他的一些库里都用到了红黑树,这是因为红黑树是不追求完全平衡的是一种近似平衡的二叉树保证最长路径不超过最短路径的二倍,相对于AVL树来说降低了旋转的要求,所以性能会优于AVL树(这篇文章主要介绍红黑树的插入).

    在上面提到了红黑树的特性是保证最长路径不超过最短路径的二倍,那仫为什仫满足这样的要求就是红黑树了呢?让我先来介绍一下红黑树的性质>

    1).每个结点不是红色就是黑色.

    2).根结点是黑色的.

    3).如果一个结点是红色的,则它的两个子节点是黑色的(不存在连续的红结点).

    4).对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点(每条路径上黑色结点的数量相等)

    5).每个叶子结点都是黑色的(这里的叶子结点指的是空结点).

    假设有这样的一棵树它的所有节点都是黑色的,而且满足红黑树的特性,此时再次插入新的结点要重新满足红黑树的特性4,我们只能插入红色结点,而且插入新的红色结点为了满足特性3,只能在黑色结点之间插入新的红色结点,此时最长路径上的结点数量恰好满足不超过最短路径的两倍.

   

 红黑树的插入>

      为了满足红黑树的特性4,所以新插入的结点的颜色必须为红色.

      当前结点cur为红色,parent为红色,则必然存在祖父结点.因为不能存在连续的红色结点,所以祖父结点的颜色一定是黑色的.根据uncle是否存在以及uncle结点的颜色来进行不同的处理.

      (1).uncle存在且uncle为红.

         

      (2).uncle不存在或者uncle为黑色.

         

    通过上图观察可得情况3和情况2类似,可以将情况3先进行左单旋变成和情况2类似的情况再进行右单旋,最后达到处理的效果.

    

           

    在进行双旋的时候,因为双旋是分成单旋来完成的所以双旋完成第一次单旋后要修改parent和cur指针否则就会导致丢失结点的现象.

 

     (3).当parent->_right == cur时和上述情况类似,在这里我就不多加叙述了.

 代码实现区>

     

#pragma once

enum Colour
{
	RED,
	BLACK
};

template<class K,class V>
struct RBTreeNode
{
	K _key;
	V _value;
	RBTreeNode<K,V>* _left;
	RBTreeNode<K,V>* _right;
	RBTreeNode<K,V>* _parent;
	Colour _color;
	RBTreeNode(const K& key,const V& value)
		:_key(key)
		,_value(value)
		,_left(NULL)
		,_right(NULL)
		,_parent(NULL)
		,_color(RED)
	{}
};

template<class K,class V>
class RBTree
{
	typedef RBTreeNode<K,V> Node;
public:
	RBTree()
		:_root(NULL)
	{}
	bool Insert(const K& key,const V& value)
	{
		if(_root == NULL)
		{
			_root=new Node(key,value);
			_root->_color=BLACK;
			return true;
		}
		Node *parent=NULL;
		Node *cur=_root;
		while (cur)
		{
			if (cur->_key < key)
			{
				parent=cur;
				cur=cur->_right;
			}
			else if (cur->_key > key)
			{
				parent=cur;
				cur=cur->_left;
			}
			else
				return false;
		}
		cur=new Node(key,value);
		cur->_parent=parent;
		if(parent->_key < key)
			parent->_right=cur;
		else
			parent->_left=cur;
		while (cur != _root && parent->_color == RED)   //保证有父亲和祖父
		{
			Node *grandfather=parent->_parent;
			if (grandfather->_left == parent)
			{
				Node *uncle=grandfather->_right;
				if (uncle && uncle->_color == RED)      //情况1
				{
					parent->_color=uncle->_color=BLACK;
					grandfather->_color=RED;
					//继续向上调整
					cur=grandfather;
					parent=cur->_parent;
				}
				else     //uncle不存在或者uncle为黑色
				{
					if (parent->_right == cur)          //情况3
					{
						_RotateL(parent);
						//第一次旋转完成后更新parent和cur
						swap(parent,cur);
					}
					_RotateR(grandfather);              //情况2
					grandfather->_color=RED;
					parent->_color=BLACK;
					break;
				}
			}
			else      //grandfather->_right == parent
			{
				Node *uncle=grandfather->_left;
				if(uncle && uncle->_color == RED)
				{
					parent->_color=uncle->_color=BLACK;
					grandfather->_color=RED;
					cur=grandfather;
					parent=cur->_parent;
				}
				else     //uncle不存在或者uncle为黑色
				{
					if (parent->_left == cur)
					{
						_RotateR(parent);
						swap(parent,cur);
					}
					_RotateL(grandfather);
					grandfather->_color=RED;
					parent->_color=BLACK;
					break;
				}
			}
		}
		_root->_color=BLACK;
		return true;
	}
	bool Find(const K& key)
	{
		if(_root == NULL)
			return false;
		Node *cur=_root;
		while (cur)
		{
			if(cur->_key < key)
				cur=cur->_right;
			else if(cur->_key > key)
				cur=cur->_left;
			else
				return true;
		}
		return false;
	}
	void InOrder()
	{
		_InOrder(_root);
		cout<<endl;
	}
	bool IsRBTree()
	{
		if(_root == NULL)
			return true;
		if(_root->_color == RED)       //判断根结点是否是黑色
			return false;
		int count=0;
		Node *cur=_root;
		while (cur)
		{
			if(cur->_color == BLACK)
				count++;
			cur=cur->_left;
		}
		int k=0;
		return _IsRBTree(_root,count,k);
	}
	~RBTree()
	{
		_Destroy(_root);
	}
protected:
	bool _IsRBTree(Node *root,const int count,int k)
	{
		if(root == NULL)
			return true;
		if (root->_color == RED && root->_parent->_color == RED)
		{
			cout<<"存在连续的红结点:"<<root->_key<<endl;
			return false;
		}
		if(root->_color == BLACK)
			++k;
		if (root->_left == NULL && root->_right == NULL)
		{
			if(count != k)
			{
				cout<<"黑色结点的数量不等"<<root->_key<<endl;
				return false;
			}
		}
		return _IsRBTree(root->_left,count,k) && _IsRBTree(root->_right,count,k);
	}
	void _RotateL(Node *parent)
	{
		Node *subR=parent->_right;
		Node *subRL=subR->_left;
		parent->_right=subRL;
		if(subRL)
			subRL->_parent=parent;
		subR->_left=parent;
		Node *ppNode=parent->_parent;
		parent->_parent=subR;
		if (ppNode == NULL)
		{
			_root=subR;
			subR->_parent=NULL;
		}
		else
		{
			if(ppNode->_left == parent)
				ppNode->_left=subR;
			else
				ppNode->_right=subR;
			subR->_parent=ppNode;
		}
	}
	void _RotateR(Node *parent)
	{
		Node *subL=parent->_left;
		Node *subLR=subL->_right;
		parent->_left=subLR;
		if(subLR)
			subLR->_parent=parent;
		subL->_right=parent;
		Node *ppNode=parent->_parent;
		parent->_parent=subL;
		if (ppNode == NULL)
		{
			_root=subL;
			subL->_parent=NULL;
		}
		else
		{
			if(ppNode->_left == parent)
				ppNode->_left=subL;
			else
				ppNode->_right=subL;
			subL->_parent=ppNode;
		}
	}
	void _InOrder(Node *root)
	{
		if(root == NULL)
			return ;
		_InOrder(root->_left);
		cout<<root->_key<<" ";
		_InOrder(root->_right);
	}
	void _Destroy(Node *&root)
	{
		if(root == NULL)
			return ;
		Node *cur=root;
		if (cur)
		{
			_Destroy(cur->_left);
			_Destroy(cur->_right);
			delete cur;
			cur=NULL;
		}
	}
protected:
	Node *_root;
};


 

    

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值