红黑树--(上)

    红黑树是应用的最多的二叉树之一,包括STL中的map和set,以及Linux的内核等等都使用到了红黑树。今天花了一下午的时间实现了红黑树的一些功能,主要是插入节点的情况分析(删除节点还在研究)。

    首先红黑树的性质比较重要,这里就简单的说一下吧!

     性质1. 节点是红色或黑色。

     性质2. 根节点是黑色。

     性质3. 每个叶节点是黑色的。

     性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

     性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

   其中最重要的是最后两条,它的特性体现在这两条规则上,记住这两条规则后你就能比较清楚的理解红黑树了。

   我设计的红黑树的节点的形式如下:

template<class K,class V>
struct RedBlackTreeNode
{
	K			  _key;     //键
	V			  _val;	    //值
	Color			  _color;   //颜色
	RedBlackTreeNode<K, V>*   _parent;  //父节点 
	RedBlackTreeNode<K, V>*   _left;    //左子节点 
	RedBlackTreeNode<K, V>*   _right;   //右子节点
	
	RedBlackTreeNode(const K& key, const V& val)
		: _key(key)
		, _val(val)
		, _color(Red)
		, _parent(NULL)
		, _left(NULL)
		, _right(NULL)
	{}
};
下面我就分析一下红黑树插入节点时候的情况。






常见的情况有上述几种,不过我这里只画出了一半(左半边),右半边和左半边对称,相信凭大家的能力,这点东西算不了什么,所以我们大概只需要考虑这几种情况就行了,在实现的时候将右半边加上就好了,下面我就给出代码,参考一下:

#pragma once

#include <iostream>
using namespace std;

enum Color
{
	Red,
	Black
};

template<class K,class V>
struct RedBlackTreeNode
{
	K			  _key;      //键
	V			  _val;	     //值
	Color			  _color;    //颜色
	RedBlackTreeNode<K, V>*   _parent;   //父节点 
	RedBlackTreeNode<K, V>*   _left;     //左子节点 
	RedBlackTreeNode<K, V>*   _right;    //右子节点
	
	RedBlackTreeNode(const K& key, const V& val)
		: _key(key)
		, _val(val)
		, _color(Red)
		, _parent(NULL)
		, _left(NULL)
		, _right(NULL)
	{}
};

template<class K,class V>
class RedBlackTree
{
	typedef RedBlackTreeNode<K, V> Node;
public:
	RedBlackTree()
		:_root(NULL)
	{}

	void InOrder()
	{
		_InOrder(_root);
	}
	
	Node* Find(const K &key)
	{
		Node *cur = _root;
		while (cur)
		{
			if (cur->_key == key)
			{
				return cur;
			}
			else if(key < cur->_key)
			{
				cur = cur->_left
			}
			else
			{
				cur = cur->_right;
			}
		}
		return cur;
	}

	bool Insert(const K &key, const V &val)
	{
		if (_root == NULL)
		{
			_root = new Node(key, val);
			_root->_color = Black;
			return true;
		}

		//找插入点
		Node *parent = NULL;
		Node *cur = _root;
		while (cur)
		{
			parent = cur;
			if (cur->_key == key)
				return false;
			else if (cur->_key < key)
				cur = cur->_right;
			else
				cur = cur->_left;
		}

		//连接节点
		cur = new Node(key, val);
		cur->_parent = parent;
		if (parent->_key > key)
		{
			parent->_left = cur;
		}
		else
		{
			parent->_right = cur;
		}

		//根据红黑树条件调节
		while (parent != _root && parent->_color == Red) //祖父节点存在且父节点为红色
		{
			Node* grandfa = parent->_parent;
			if (grandfa->_left == parent)
			{ //新插入节点位于grandfa的左子树
				Node *uncle = grandfa->_right;
				if (uncle && uncle->_color == Red)
				{
					grandfa->_color = Red;
					parent->_color = Black;
					uncle->_color = Black;
					
					cur = grandfa;
					if (cur == _root)
					{//遍历到根了
						break;
					}
					parent = cur->_parent;
					//continue;
				}
				else
				{
					if (cur == parent->_right)
					{//左单旋
						_RotateL(parent);
						cur = cur->_left;
						parent = cur->_parent;
					}
					//右单旋
					_RotateR(grandfa);
					parent->_color = Black;
					parent->_left->_color = Red;
					parent->_right->_color = Red;
					break;
				}
			}
			else
			{ //新插入节点位于grandfa的右子树
				Node *uncle = grandfa->_left;
				if (uncle && uncle->_color == Red)
				{
					grandfa->_color = Red;
					parent->_color = Black;
					uncle->_color = Black;

					cur = grandfa;
					if (cur == _root)
					{
						break;
					}
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_left)
					{ //右单旋
						_RotateR(parent);
						cur = cur->_right;
						parent = cur->_parent;
					}
					//左单旋
					_RotateL(grandfa);
					parent->_color = Black;
					parent->_left->_color = Red;
					parent->_right->_color = Red;
					break;
				}
			}
		}
		_root->_color = Black;
		return true;
	}


	bool Remove(const K &key)
	{
		Node* pos = Find(key);
		if (pos == NULL)
		{
			return false;
		}
		/*
			未完成
		*/
		return true;
	}

	bool IsRight()
	{	
		//统计一条路径上的黑色节点的个数
		Node *cur = _root;
		int blacknum = 0;
		while (cur)
		{
			if (cur->_color == Black)
				++blacknum;
			cur = cur->_left;
		}

		return _CheckRBTree(_root,blacknum,0);
	}

	~RedBlackTree()
	{}

protected:
	bool _CheckRBTree(Node *root,int blacknum,int curblacknum)
	{
		if (root == NULL)
			return true;

		if (root->_color == Black)
		{//黑色节点
			++curblacknum;
		}
		else
		{//红色节点
			if (root->_parent && root->_parent->_color == Red)
			{//不合要求
				cout << "连续两个红色节点" << endl;
				return false;
			}
		}

		if (root->_left == NULL && root->_right == NULL)
		{//叶子结点
			if (curblacknum == blacknum)
				return true;

			return false;
		}

		return _CheckRBTree(root->_left,blacknum,curblacknum) 
			&& _CheckRBTree(root->_right,blacknum,curblacknum);
	}

	void _InOrder(Node *root)
	{
		if (root)
		{
			_InOrder(root->_left);
			cout << "[" << root->_key << "," << root->_val << "] ";
			_InOrder(root->_right);
		}
	}

	void _RotateL(Node *&parent)
	{ //左单旋
		Node *subR = parent->_right;
		Node *subRL = subR->_left;

		if (subRL)
		{ //如果存在
			subRL->_parent = parent;
		}
		subR->_parent = parent->_parent;		
		parent->_parent = subR;
		subR->_left = parent;
		parent->_right = subRL;
		parent = subR;
		if (parent->_parent)
		{
			Node* grandfa = parent->_parent;
			if (grandfa->_key > parent->_key)			
				grandfa->_left = parent;			
			else			
				grandfa->_right = parent;
		}
		else
		{
			_root = parent;
		}
	}
	
	void _RotateR(Node *&parent)
	{ //右单旋
		Node* subL = parent->_left;
		Node *subLR = subL->_right;

		if (subLR)
		{
			subLR->_parent = parent;
		}
		subL->_parent = parent->_parent;
		parent->_parent = subL;
		subL->_right = parent;
		parent->_left = subLR;
		parent = subL;
		if (parent->_parent)
		{
			Node *grandfa = parent->_parent;
			if (grandfa->_key > parent->_key)
				grandfa->_left = parent;
			else
				grandfa->_right = parent;
		}
		else
		{
			_root = parent;
		}
	}

protected:
	Node	*_root;
};

void TestRedBlackTree()
{
	RedBlackTree<int, int> rb;
	rb.Insert(3, 1);
	rb.Insert(2, 1);
	rb.Insert(1, 1);
	rb.Insert(5, 1);
	rb.Insert(8, 1);
	rb.Insert(6, 1);
	rb.Insert(7, 1);
	rb.InOrder();
	cout <<endl<< "isRBTree ? " << rb.IsRight() << endl;
}
      这里我主要是实现的是红黑树的插入功能,以及中序遍历,以及检查红黑树是否正确,红黑树的删除还待研究一下,下次补充上来,大家对于上面的过程有什么问题可以给我留言,若是还有不足的地方也欢迎大家指出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值