红黑树简单实现

红黑树特点:

1.根节点为黑色

2.每个红色节点的左右孩子为黑色节点,即无连续的红结点

3.每条路径上的黑色节点相等

4.最长路径不超过最短路径的二倍


创建红黑树,在插入节点后(默认插入节点颜色为红色),要对红黑树进行判断并调整

当父节点为红色(以下情况均是父节点为祖父节点左孩子,而父节点为祖父右孩子推理可得)



相关代码:

bool Insert(const K& key, const V& value)
{
if (_root == NULL)
{
_root = new Node(key, value);
_root->color = BLACK;
return true;
}
Node* root = _root;
Node* parent = NULL;
while (root)
{
if (root->_key > key)
{
parent = root;
root = root->_left;
}
else if (root->_key < key)
{
parent = root;
root = root->_right;
}
else
return false;
}
if (parent->_key > key)
{
root=parent->_left = new Node(key, value);
root->_parent = parent;
}
else
{
root = parent->_right = new Node(key, value);
root->_parent = parent;
}
//调整红黑树颜色
while (parent&&parent->color == RED)
{
Node* Gparent = parent->_parent;
if (Gparent->_left== parent)
{
Node* uncle = Gparent->_right;
//叔叔存在且为红 直接将叔叔和父节点变黑 为保证每条路径黑色节点数相等 将祖父节点变红 
//若祖父节点为根节点则不变色
if (uncle&&uncle->color == RED)
{
parent->color = uncle->color = BLACK;
if (Gparent == _root)
break;
Gparent->color = RED;
root = Gparent;
parent = root->_parent;
}
//叔叔不存在或者存在且为黑 
else
{
if (root == parent->_right)
{
RotateL(parent);
swap(root, parent);
//左旋后当前结点和父节点位置交换 为防止下面右旋(旋转父节点)对象错误,交换两节点
}
RotateR(Gparent);
//交换后变色处理
parent->color = BLACK;
Gparent->color = RED;
}
}
else
{
Node* uncle = Gparent->_left;
if (uncle&&uncle->color == RED)
{
parent->color = uncle->color = BLACK;
if (Gparent == _root)
break;
Gparent->color = RED;
root = Gparent;
parent = root->_parent;
}
else
{
if (root == parent->_left)
{
    RotateR(parent);
swap(root, parent);
}
RotateL(Gparent);
parent->color = BLACK;
Gparent->color = RED;
}
}

}
return true;
}

红黑树创建完成后要判断当前树是否为红黑树

判断1.每条路径黑色节点是否相等 

先找出一条路径的黑节点个数作为判断依据,再遍历这棵树每条路径

2.是否有连续的红节点

当前结点为红色时,其父节点一定存在,判断其父节点是否为红结点即可

相关代码:

bool _BCount(Node* cur, size_t Bcount, size_t n)//判断每条路径黑节点数是否相等
{
if (cur)
{
if (cur->color == BLACK)
n++;
if (cur->_left == NULL&&cur->_right == NULL)
{
if (n != Bcount)
return false;
}
_BCount(cur->_left, Bcount, n);
_BCount(cur->_right, Bcount, n);
}
return true;
}

bool _Rcont(Node* cur)//判断是否有连续红节点
{
if (cur)
{
if (cur->color == RED)
{
if (cur->_parent->color == RED)
return false;
}
_Rcont(cur->_left);
_Rcont(cur->_right);
}
return true;
}

红黑树完整代码:

#include<iostream>
#include<stack>
using namespace std;
enum Color{ RED, BLACK };
template < typename K, typename V>
struct REDTreeNode
{
	REDTreeNode<K, V>* _left;
	REDTreeNode<K, V>* _right;
	REDTreeNode<K, V>* _parent;
	Color color = RED;
	K _key;
	V _value;
	REDTreeNode(const K& key, const V& value)
		:_left(NULL)
		, _right(NULL)
		, _parent(NULL)
		, _key(key)
		, _value(value)
	{}
};

template<typename K,typename V>
class RBTree
{
public:
	typedef REDTreeNode<K, V> Node;
	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* root = _root;
		Node* parent = NULL;
		while (root)
		{
			if (root->_key > key)
			{
				parent = root;
				root = root->_left;
			}
			else if (root->_key < key)
			{
				parent = root;
				root = root->_right;
			}
			else
				return false;
		}
		if (parent->_key > key)
		{
			root=parent->_left = new Node(key, value);
			root->_parent = parent;
		}
		else
		{
			root = parent->_right = new Node(key, value);
			root->_parent = parent;
		}
		//调整红黑树颜色
		while (parent&&parent->color == RED)
		{
			Node* Gparent = parent->_parent;
			if (Gparent->_left== parent)
			{
				Node* uncle = Gparent->_right;
//叔叔存在且为红 直接将叔叔和父节点变黑 为保证每条路径黑色节点数相等 将祖父节点变红 
				//若祖父节点为根节点则不变色
				if (uncle&&uncle->color == RED)
				{
					parent->color = uncle->color = BLACK;
					if (Gparent == _root)
						break;
					Gparent->color = RED;
					root = Gparent;
					parent = root->_parent;
				}
				//叔叔不存在或者存在且为黑 
				else
				{
					if (root == parent->_right)
					{
						RotateL(parent);
						swap(root, parent);
			//左旋后当前结点和父节点位置交换 为防止下面右旋(旋转父节点)对象错误,交换两节点
					}
						RotateR(Gparent);
						//交换后变色处理
						parent->color = BLACK;
						Gparent->color = RED;
				}
			}
			else
			{
				Node* uncle = Gparent->_left;
				if (uncle&&uncle->color == RED)
				{
					parent->color = uncle->color = BLACK;
					if (Gparent == _root)
						break;
					Gparent->color = RED;
					root = Gparent;
					parent = root->_parent;
				}
				else
				{
					if (root == parent->_left)
					{
				     RotateR(parent);	
					 swap(root, parent);
					}
					RotateL(Gparent);
					parent->color = BLACK;
					Gparent->color = RED;
				}
			}
			
		}
		return true;
	}
	void RotateL(Node* root)
	{
		_RotateL(root);
	}
	void RotateR(Node* root)
	{
		_RotateR(root);
	}
	bool IsRBTree()//无连续红节点,每天路径黑节点数相等,头节点为黑
	{
		if (_root->color !=BLACK)
			return false;
		Node* root = _root;
		size_t Bcount = 0;
		size_t n = 0;
		while (root)
		{
			if (root->color == BLACK)
				Bcount++;
			root = root->_left;
		}
		return _IsRBTree(_root, Bcount,n);
	}
	void InOrder()
	{
		_InOrder(_root);
	}
protected:
	void _InOrder(Node* root)
	{
		if (root == NULL)
			return;
		_InOrder(root->_left);
		cout << root->_key << " ";
		_InOrder(root->_right);
	}
	bool _BCount(Node* cur, size_t Bcount, size_t n)
	{
		if (cur)
		{
			if (cur->color == BLACK)
				n++;
			if (cur->_left == NULL&&cur->_right == NULL)
			{
				if (n != Bcount)
					return false;
			}
			_BCount(cur->_left, Bcount, n);
			_BCount(cur->_right, Bcount, n);
		}
		return true;
	}
	bool _Rcont(Node* cur)
	{
		if (cur)
		{
			if (cur->color == RED)
			{
				if (cur->_parent->color == RED)
					return false;
			}
			_Rcont(cur->_left);
			_Rcont(cur->_right);
		}
		return true;
	}
	bool _IsRBTree(Node* root, size_t Bcount,size_t n)
	{	
		if (false == _BCount(root, Bcount, n))//判断每条路径黑节点数是否相等
			return false;
		if (false == _Rcont(root))//判断是否有连续红节点
			return false;
		return true;
	}
	void _RotateL(Node* root)//左旋
	{
		if (root == NULL)
			return;
		Node* subR = root->_right;
		Node* subRL = subR->_left;
		Node* ppNode = root->_parent;
		subR->_left = root;
		root->_parent = subR;
		if (subRL)
		{
			root->_right = subRL;
			subRL->_parent = root;
		}
		else
			root->_right = NULL;
		if (ppNode)
		{
			if (ppNode->_left == root)
				ppNode->_left = subR;
			else
			    ppNode->_right = subR;
			subR->_parent = ppNode;
		}
		else
		{
			_root = subR;
			_root->_parent = NULL;
		}
	}
	void _RotateR(Node* root)//右旋
	{
		if (root == NULL)
			return;
		Node* subL = root->_left;
		Node* subLR = subL->_right;
		Node* ppNode = root->_parent;
		subL->_right = root;
		root->_parent = subL;
		if (subLR)
		{
			root->_left = subLR;
			subLR->_parent = root;
		}
		else
			root->_left = NULL;
		if (ppNode)
		{
			if (ppNode->_left == root)
				ppNode->_left = subL;
			else
				ppNode->_right = subL;
			subL->_parent = ppNode;
		}
		else
		{
			_root = subL;
			_root->_parent = NULL;
		}
	}
private:
	Node* _root;
};


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值