浅析红黑树

红黑树:首先红黑树是一颗搜索二叉树,树中的每个结点不是红色就是黑色。它的特征如下:
1.根节点是黑色

2.每个结点不是黑色就是红色

3.不能有两个连续的红结点

4.每条路径上黑色结点数量相同

为什么要有红黑树?

最开始我们学习了搜索二叉树,但是搜索二叉树有可能出现单链的情况,之后我们又引入了AVL树,AVL树是一种高度平衡的二叉搜索树。能够满足增加,删除,查找都是o(lg N)的时间复杂度,为什莫还要引入红黑树呢?

这时由于AVL树是高度平衡二叉搜索树,维持一颗AVL树的代价相比红黑树要大很多,由于它的高度平衡,使得几乎每次插入或者删除都要调整树。而红黑树是一颗近似平衡的二叉搜索树,它满足最长路径不超过最短路径的两倍,易于维护。而且红黑树效率最短路径lgN,最长路径2LgN
三  
思考为什莫红黑树满足它的性质,就能保证最长路径不超过最短路径的两倍。。。最短,全黑,最长,每个黑的中间加个红

最多也就二倍,因此保证了最长路径不超过最短路径的两倍

四    插入

一般默认插入的结点是红的(如果黑的,每条路径上都要增加)

1.如果要插入的结点是根节点,则直接插入,并将根节点染为黑色

2.如果插入位置父亲是黑色,直接插入
3.如果要插入位置的父亲是红色的,这时如果再插入一个红色结点,就会出现两个连续的红色结点。

假如要插入的结点是cur,它的父亲是parent,它的父亲的兄弟是uncle,它的祖父是grandfather.
分为两种情况1.叔叔存在且为红

                     2.叔叔不存在,或者叔叔为黑


#pragma once
#include<iostream>
using namespace std;
enum color
{
	RED,
	BLACK
};
template<class K,class V>
struct RBTreeNode
{

	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>*_right;
	RBTreeNode<K, V>*_parent;
	K _key;
	V _value;
	color _cor;
	RBTreeNode (const K&key,const V&value )
		:_left ( NULL )
		, _right ( NULL )
		, _parent (NULL )
		, _key (key )
		, _value (value)
		, _cor (RED )
	{}

};
template<class K,class V>
class RBTree
{public:
	typedef RBTreeNode<K, V> Node;
	RBTree ( )
		:_Root ( NULL )
	{}
	bool Insert ( const K& key, const V& value )
	{
		if ( _Root == NULL )
		{
			_Root = new Node ( key, value );
			_Root->_cor = BLACK;
			return true;
		}
		Node* cur = _Root;
		Node* parent = NULL;
		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 = new Node ( key, value );
		if ( parent->_key > key )
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		//检查
		//1.parent为黑
		//2.parent为红,叔叔存在且为红
		//3.parent为红,叔叔不存在,或者叔叔存在且为黑
		while (parent&& parent->_cor == RED )
		{
			Node* Grandfather = parent->_parent;
			if ( parent == Grandfather->_left )
			{
				Node* uncle = Grandfather->_right;

				if( uncle&&uncle->_cor == RED)//叔叔存在且为红色
				{
					uncle->_cor = parent->_cor = BLACK;
					Grandfather->_cor = RED;//继续往上调
					cur = Grandfather;
					parent = cur->_parent;
				}
				else//叔叔不存在或者叔叔等于黑
				{  //双旋
					if ( cur == parent->_right )
					{
						RotateL (parent );
						swap(parent, cur);
					}
					//单旋
					RotateR ( Grandfather );
					parent->_cor = BLACK;
					Grandfather->_cor = RED;
					
				}
			}
			else
			{
				Node* uncle = Grandfather->_left;
				if ( uncle&&uncle->_cor == RED )//叔叔存在且为红
				{
					parent->_cor = uncle->_cor = BLACK;
					Grandfather->_cor = RED;//继续向上调整
					cur = Grandfather;
					parent = cur->_parent;
				}
				else//叔叔不存在,或者叔叔存在且为黑
				{
					if ( cur == parent->_left )
					{
						RotateR ( parent );
						swap(parent, cur);
					}
					RotateL ( Grandfather );
					Grandfather->_cor = RED;
					parent->_cor = BLACK;
				}
			}
		}
		_Root->_cor = BLACK;
		return true;
	}
	void RotateR ( Node*parent )
	{
		Node*subL = parent->_left;
		Node* subLR = subL->_right;
		Node*ppNode = parent->_parent;
		parent->_left = subLR;
		if ( subLR )
		{
			subLR->_parent = parent;
		}
		subL->_right = parent;
		parent->_parent = subL;
		if ( ppNode == NULL )
		{
			_Root = subL;
			_Root->_parent = NULL;
		}
		else 
		{
			if ( ppNode->_left == parent )
			ppNode->_left = subL;
			else
			ppNode->_right = subL;
			subL->_parent = ppNode;
		}
		
	}
	void RotateL ( Node*parent )
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		Node* ppNode = parent->_parent;
		parent->_right = subRL;
		if ( subRL )
		{
			subRL->_parent = parent;
		}
		subR->_left = parent;
		parent->_parent = subR;
		if ( ppNode == NULL )
		{
			_Root = subR;
			_Root->_parent = NULL;
		}
		else if ( ppNode->_left == parent )
		{
			ppNode->_left = subR;
		}
		else
		{
			ppNode->_right = subR;
		}
		subR->_parent == ppNode;
	}
	void Inorder ( )
	{
		_Inorder ( _Root );
		cout << endl;
	}
	void _Inorder ( Node*Root )
	{
		if (Root == NULL )
		{
			return ;
		}
		_Inorder ( Root->_left );
		cout << Root -> _key << " ";
		_Inorder ( Root->_right );
	}
	bool Isbalance ( )//判断是否平衡    //首先我们会想到拿高度判断,最长不超多最短二倍 但是颜色可能不符合,因此不能仅仅拿高度来判断
		//判断:1.根是黑的  2.没有连续红色结点  (递归遍历) 3.每条路径上黑色结点数目相等
	{
		if ( _Root->_cor == RED )
		{
			return false;
		}
		int k = 0;
		int blacknum = 0;
		Node* cur = _Root;
		while ( cur )
		{
			if ( cur->_cor == BLACK )
			{
				k++;
			}
			cur = cur->_left;
		}
		return _IsBalance ( _Root,k,blacknum );

	}
private://注意此处blacknum不能给引用
	bool _IsBalance ( Node* cur, const int& k,int blacknum )//想想我们如何判断每个路径上黑色结点数量相同   有的人会说用容器存  空间复杂度 即为最后一层结点数 2^(log 2 N)-1  也就是O(N)显然是不行的
	{
		               //因此我们不妨先把最左边,或者最右边一条路径上黑节点算出来,然后和其他路径上对比,如果有不同,说明每条路径上黑色结点树不同
		if ( cur == NULL )
		{
			if ( blacknum != k )
			{
				cout << "黑节点数目不想等" << " " << endl;
				return false;
			}
			else
			{

				return true;
			}
		}
		Node* parent = cur->_parent;
		if (( cur->_cor == RED)&&(parent->_cor == RED ))//注意,一般我们会想如何判断没有连续红节点,回想着判断它的左右孩子是否为红。这样还要考虑左孩子,右孩子
		{                                           //此处 我们不妨逆着来想,反正每个结点会被遍历到,判断它的父亲是否为红。
			cout << "存在连续的红色结点" << cur->_key << endl;
			return false;
		}
			if ( cur->_cor == BLACK )
			{
				blacknum++;
			}
			return _IsBalance ( cur->_left, k, blacknum ) && _IsBalance ( cur->_right, k, blacknum );
	}
private:
	Node* _Root;
};
void Test ( )
{
	int arr[] = {16,3,7,11,9,26,18,14};
	RBTree<int, int>t1;
	for ( int i = 0; i < sizeof(arr) / sizeof (arr[0]); i++ )
	{
		t1.Insert ( arr[i],i);
		cout <<arr[i]<<" "<<"Isbalance?"<< t1.Isbalance ( ) << endl;
	}
	t1.Inorder ();
	cout<<t1.Isbalance ( )<<endl;
}

猜你喜欢

转载自blog.csdn.net/baidu_37964044/article/details/79983285