【データ構造】マホガニーツリー


マホガニーツリーは、RedまたはBlackであり得るノードの色を表すために、各ノードに格納ビットを追加した二叉探索ツリーである.根から葉までの簡単な経路を通して
色は制約され、赤と黒の木は最長経路が最短経路の2倍を超えないことを保証し、したがって平衡に近い.
  • マホガニーは、以下のマホガニー特性を満たす二叉探索ツリー
  • である.
  • 各ノードは、赤ではなく、黒の
  • である.
  • 本のノードは黒い
  • です.
  • ノードが赤色である場合、その2つのサブノードは黒である(連続した赤ノードがない)
  • .
  • は、各ノードに対して、ノードからそのすべての後代のリーフノードへの簡単なパス上に、同じ数の黒いノードを含む.(各経路の黒いノードの数が等しい)
  • Test.cpp(主関数)
    #include
    using namespace std;
    
    #include"RBTree.h"
    
    int main()
    {
    	TestTree();
    	getchar();
    	return 0;
    }
    RBTree.h(   )
    #pragma once
    
    enum Color
    {
    	RED,
    	BLACK,
    };
    
    template
    struct RBTreeNode
    {
    	K _key;
    	V _value;
    
    	RBTreeNode* _left;
    	RBTreeNode* _right;
    	RBTreeNode* _parent;
    
    	Color _color;
    
    	RBTreeNode(const K& key,const V& value)
    		:_key(key)
    		,_value(value)
    		,_left(NULL)
    		,_right(NULL)
    		,_parent(NULL)
    		,_color(RED)
    	{}
    };
    
    template
    class RBTree
    {
    	typedef RBTreeNode 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* cur = _root;
    		Node* parent = NULL;
    		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);
    		if(parent->_key > key)
    		{
    			parent->_left = cur;
    			cur->_parent = parent;
    		}
    		else if(parent->_key < key)
    		{
    			parent->_right = cur;
    			cur->_parent = parent;
    		}
    
    		//     
    		while(cur != _root && parent->_color == RED)
    		{
    			Node* grandfather = parent->_parent;
    			if (parent == grandfather->_left)
    			{
    				Node* uncle = grandfather->_right;
    				//   1:cur  ,p  ,g  ,u     
    				if (uncle && uncle->_color == RED)
    				{
    					parent->_color = BLACK;
    					uncle->_color = BLACK;
    					grandfather->_color = RED;
    
    					cur = grandfather;
    					parent = cur->_parent;
    				}
    				//     ,      
    				else if((uncle == NULL) || (uncle != NULL && uncle->_color == BLACK))
    				{
    					//  3:cur  ,p  ,g  ,u   /u  (cur parent    )
    					//  2:cur  ,p  ,g  ,u   /u  (cur parent    )
    					if (parent->_right == cur)
    					{
    						RotateL(parent);
    						swap(cur,parent);
    					}
    					parent->_color = BLACK;
    					grandfather->_color = RED;
    					RotateR(grandfather);
    					break;
    				}
    			}
    			else // parent == grandfather->_right
    			{
    				Node* uncle = grandfather->_left;
    				if (uncle && uncle->_color == RED)//    ,    
    				{
    					parent->_color = uncle->_color = BLACK;
    					grandfather->_color = RED;
    
    					cur = grandfather;
    					parent = cur->_parent;
    				}
    				//     ,      
    				else if((uncle == NULL) || (uncle != NULL && uncle->_color == BLACK))
    				{
    					if (cur == parent->_left)
    					{
    						RotateR(parent);
    						swap(cur,parent);
    					}
    					parent->_color = BLACK;
    					grandfather->_color = RED;
    					RotateL(grandfather);
    					break;
    				}
    			}
    		}
    		_root->_color = BLACK;//        
    		return true;
    	}
    
    	void RotateL(Node* parent)
    	{
    		Node* subR = parent->_right;
    		Node* subRL = subR->_left;
    		parent->_right = subRL;
    		if(subRL)
    		{
    			subRL->_parent = parent;
    		}
    		Node* ppNode = parent->_parent;
    		subR->_left = parent;
    		parent->_parent = subR;
    
    		if(ppNode == NULL)
    		{
    			_root = subR;
    			subR->_parent = NULL;
    		}
    		else
    		{
    			if(ppNode->_left == parent)
    			{
    				ppNode->_left = subR;
    				subR->_parent = ppNode;
    			}
    			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;
    		}
    
    		Node* ppNode = parent->_parent;
    		subL->_right = 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()
    	{
    		return _InOrder(_root);
    		cout<_color == BLACK)
    			{
    				BlackCount++;
    			}
    			cur = cur->_left;
    		}
    		int curBlackCount = 0;
    		return _IsBlance(_root,BlackCount,curBlackCount);
    	}
    
    	Node* Find(const K& key)
    	{
    		return _Find(_root,key);
    	}
    	bool Remove(const K& key)
    	{}
    
    protected:
    	Node* _Find(Node* root,const K& key)
    	{
    		if(_root == NULL)
    		{
    			return NULL;
    		}
    		while(root)
    		{
    			if(root->_key == key)
    			{
    				cout<_key<_value<_key > key)
    				root = root->_left;
    			else
    				root = root->_right;
    		}
    		
    		cout<_color == RED)
    		{
    			return false;
    		}
    		//3.          
    		if(root->_color == BLACK)
    		{
    			curBlackCount++;
    		}
    		else
    		{
    			if(root->_parent && root->_parent->_color == RED)
    			{
    				cout<_key<_left == NULL && root->_right == NULL)
    		{
    			if(BlackCount == curBlackCount)
    			{
    				return true;
    			}
    			else
    			{
    				cout<_key<_left,BlackCount,curBlackCount)
    			&& _IsBlance(root->_right,BlackCount,curBlackCount);
    
    	}
    
    	void _InOrder(Node* root)
    	{
    		if(root == NULL)
    		{
    			return;
    		}
    		_InOrder(root->_left);
    		cout<_key<_right);
    	}
    protected:
    	Node* _root;
    };
    
    
    void TestTree()
    {
    	RBTree tree;
    	int array[]={16, 3, 7, 11, 9, 26, 18, 14, 15};
    	for(size_t i = 0; i < sizeof(array)/sizeof(array[0]); ++i)
    	{
    		tree.Insert(array[i],i);
    	}
    	tree.InOrder();
    	cout<
    挿入する5つのシナリオ:
    状況1:この木は空の木で、直接にルートの結点の位置を挿入して、性質1に違反して、ノードの色を赤から黒に変えてもいいです.
     
    ケース2:挿入ノードNの親ノードPは黒であり、いかなる性質にも違反しない.
     
    ケース3:curは赤、pは赤、gは黒、uは存在してかつ赤い
    操作:p、uを黒に変え、gを赤に変え、gをcurとして上に調整します.
    ケース4:curは赤、pは赤、gは黒、uは存在しない/uは黒
    操作:pはgの左の子供で、curはpの左の子供で、右のシングル回転を行います.反対に、pはgの右の子供で、curはpの右の子供で、左単回転を行います.
    p、g変色--pが黒くなり、gが赤くなります.
    ケース5:curは赤、pは赤、gは黒、uは存在しない/uは黒
    操作:pはgの左の子供で、curはpの右の子供で、pに対して左単回転をします.反対に、pはgの右の子供で、curはpの左の子供で、pに対して右のシングル回転をします.
    場合4に変換します.