【データ構造】マホガニーツリー
マホガニーツリーは、RedまたはBlackであり得るノードの色を表すために、各ノードに格納ビットを追加した二叉探索ツリーである.根から葉までの簡単な経路を通して
色は制約され、赤と黒の木は最長経路が最短経路の2倍を超えないことを保証し、したがって平衡に近い.マホガニーは、以下のマホガニー特性を満たす二叉探索ツリー である.各ノードは、赤ではなく、黒の である.本のノードは黒い です.ノードが赤色である場合、その2つのサブノードは黒である(連続した赤ノードがない) .は、各ノードに対して、ノードからそのすべての後代のリーフノードへの簡単なパス上に、同じ数の黒いノードを含む.(各経路の黒いノードの数が等しい) Test.cpp(主関数)
状況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に変換します.
色は制約され、赤と黒の木は最長経路が最短経路の2倍を超えないことを保証し、したがって平衡に近い.
#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に変換します.