RBTree的模拟实现

RBTree:是一二叉搜索树,每个节点增加一个存储位来表示节点的颜色,通过任何一条路径的从根节点到叶子简单路径上的颜色来约束,红黑树保证了最长路径不超过最短路径的两倍,因而近乎平衡。

RBTree满足的性质:1.每个节点的颜色不是黑色就是红色

                                 2.跟节点的颜色一定是黑色

                                 3.如果一个节点是红色的,则他的两个子节点是黑色的,即没有连续的红节点

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


当满足上述的性质时,红黑树自然可以保证最长的路径不超过最短路径的两倍,因为最长的路径一定是在每个黑节点后面跟了一个红节点,而最短路径一定只有黑色节点,这样就保证了上述的结论。

最长路径:黑->红->黑->红->黑->红

最短路径:黑->黑->黑



为了满足上述的性质,我们再插入时,选择每次都默认插入的是红色的节点,因为我们不想破坏第四条性质,因为维护起来相当的麻烦,当你变了一条路径的黑色节点数目是有可能整棵树都要做出调整,因为你改变的这条路径可能是一条子树,那么就很麻烦了,你需要把其他所有路径的都要改变黑色数目来维护这条性质,这样的工作实在是很难,需要注意很多的地方。但是我们插入默认是红色节点也会破坏它的第三条性质,但是这里第三条的性质比起第四条还是简单了许多的,所以我们选择破坏第三条,而不是第四条。这时当我们插入红节点时就可能会出现连续的红节点这样的情况,这里我们需要做出调整来满足其第三条性质。下面是其几种情况:

第一种情况:grandfather为黑,parent为红,uncle存在且为红,这时我们需要将parent和uncle变黑,再grandfather变1红,这样就没有连续的红色节点,同时使这棵树的黑色节点数没有改变,这样就很好的使这棵RBTree得到了维护,但是我们还需要向上调整,因为这棵树keen那个只是一颗子树。


第二种情况:cur为红,parent为红,grandfather为黑,uncle存在且为黑或者uncle不存在,parent为grandfather的左孩子,cur也是parent的左孩子,则这时需要以grandfather为轴进行一个右单旋,同时将parent变为黑grandfather变为红,这样黑色的节点数目还是没有改变的。

uncle存在且为黑或者uncle不存在的情况:

第三种情况:其实第二种可以说是第三种的一种特殊情况,也就是AVL的双旋和单选的问题,cur为红,parent为红,grandfather为黑,uncle存在且为黑或者uncle不存在,parent是grandfather的左孩子,cur是parent的有孩子,这是就是一双旋,现以parent为轴进行左单选,不调整颜色,再以grandfather为轴进行右单旋,同样的parent变为黑色,grandfather变为红色。


上面就是RBTree破坏第三条维持第四条之后的调整部分。

下面是我的代码部分:

#pragma once
#include<iostream>
using namespace std;
enum Color
{
	RED,
	BLEAK,
};

template<class K,class V>
struct RBTreeNode
{
	K _key;
	V _value;
	Color _col;
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;


	RBTreeNode(const K& key, const V& value)
		:_left(NULL)
		, _right(NULL)
		, _parent(NULL)
		, _key(key)
		, _value(value)
		, _col(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->_col = BLEAK;
			return true;
		}

		Node *parent = NULL;
		Node *cur = _root;
		while (cur)
		{
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else//相同的节点插不进去
			{
				return false;
			}
		}
		//此时的cur就是我们要找到的位置
		cur = new Node(key,value);
		if (parent->_key > key)
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_right = cur;
			cur->_parent = parent;
		}

		//到了这里我们已经插入了节点,这里开始判断是不是RBTree
		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;

			//如果parent是grandfather的左,那么uncle是grandfather的右
			if (parent == grandfather->_left)
			{
				Node *uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)         //叔叔存在且为红
				{
					grandfather->_col = RED;
					parent->_col = uncle->_col = BLEAK;
					cur = grandfather;
					parent = cur->_parent;
				}
				else                                    //叔叔不存在/存在是黑色的
				{
					if (cur == parent->_right)
					{
						RotateL(parent);
						swap(parent, cur);
					}
					RotateR(grandfather);
					grandfather->_col = RED;
					parent->_col = BLEAK;
					break;
				}

			}
			else  //parent=grandfather->_right
			{
				Node *uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{
					grandfather->_col = RED;
					parent->_col = uncle->_col = BLEAK;
					cur = grandfather;
					parent = cur->_parent;
				}
				else //叔叔不存在/存在是黑色的
				{
					if (cur == parent->_left)
					{
						RotateR(parent);
						swap(parent,cur);
					}
					RotateL(grandfather);
					grandfather->_col = RED;
					parent->_col = BLEAK;
					break;
				}
			}
		}
		//在调整后最后可能把根节点变红,所以我们在所有操作做完后,我们最后将root变为黑色
		_root->_col = BLEAK;                       
		return true;
	}

	//右单旋
	void RotateR(Node *cur)
	{
		Node *parent = cur->_parent;
		Node *subL = cur->_left;
		Node *subLR = subL->_right;

		if (cur == _root)
		{
			_root = subL;
			subL->_parent = NULL;
			subL->_right = cur;
		}
		else
		{
			if (cur == parent->_left)
			{
				parent->_left = subL;
			}
			else
			{
				parent->_right = subL;
			}
			subL->_parent = parent;
			subL->_right = cur;
		}

		cur->_parent = subL;
		cur->_left = subLR;

		if (subLR)
			subLR->_parent = cur;
	}

	//左单选
	void RotateL(Node *cur)
	{
	
		Node* parent = cur->_parent;
		Node* subR = cur->_right;
		Node *subRL = subR->_left;

		//当cur==_root
		if (cur == _root)
		{
			_root = subR;
			subR->_parent = NULL;
			subR->_left = cur;
		}
		else  //这时候有parent了
		{
			if (parent->_left == cur)
			{
				parent->_left = subR;
			}
			else
			{
				parent->_right = subR;
			}
			subR->_parent = parent;
			subR->_left = cur;
		}

		cur->_right = subRL;
		cur->_parent = subR;
		
		if (subRL)
			subRL->_parent = cur;
	}

	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
	void _InOrder(Node* root)
	{
		if (root == NULL)
		{
			return;
		}
		_InOrder(root->_left);
		//cout << root->_key << "->" << root->_value << " ";
		cout << root->_key <<" ";

		_InOrder(root->_right);

	}

	bool Isbalance()
	{
		size_t k = 0;
		size_t blackNum = 0;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_col == BLEAK)
				++k;

			cur = cur->_left;
		}

		return _Isbalance(_root,blackNum,k); 
	}

	bool _Isbalance(Node *root, size_t blackNum, const size_t k)   //这里blackNum不能给引用
	{
		//判断黑色节点是否相同
		if (root == NULL)                                         //这里是找到空节点,不是叶子节点
		{
			if (blackNum == k)
			{
				return true;
			}
			else
			{
				cout << "黑色节点的个数不相同"<<endl;
				return false;
			}
		}

		if (root->_col == RED && root->_parent->_col == RED)
		{
			cout << "连续的红节点" << endl;
			return false;
		}
		if (root->_col == BLEAK)
			++blackNum;

		//跑起来
		return( _Isbalance(root->_left,blackNum,k)   
			&& _Isbalance(root->_right,blackNum,k));
	}
protected:
	Node* _root;
};

//测试RBTree
void TestRBTree()
{
	RBTree<int, int > RBTree;

	int a[] = {16,3,7,11,9,26,18,14,15};
	//int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
	for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
	{
		RBTree.Insert(a[i], i);
		cout << "RBTree.Isbalence() -> " << RBTree.Isbalance() << endl;
	}
	//RBTree.Insert(16,1);
	//RBTree.Insert(3, 1);
	//RBTree.Insert(7, 1);
	//RBTree.Insert(11, 1);
	//RBTree.Insert(9, 1);
	//RBTree.Insert(26, 1);
	//RBTree.Insert(18, 1);
	//RBTree.Insert(14, 1);
	//RBTree.Insert(15, 1);




	RBTree.InOrder();
}









猜你喜欢

转载自blog.csdn.net/skinwhite/article/details/78421070