RBTree--红黑树
一.规则
1.每一个结点不是红色就是黑色。
2.根结点是黑色。
3.如果一个节点是红色,那它的两个子结点是黑色。(parent结点不能和child节点颜色同为红色)
4对每个节点来说,从该节点到其所有后代的叶子结点的简单路径上,均包含相同数目的黑色结点。
二.RNTreeNode
enum color
{
RED,
BLACK,
};
template<class K,class V>
struct RBTreeNode
{
RBTreeNode<K, V>* _parent;
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
color _col;
K _key;
V _value;
RBTreeNode(const K& key, const V& value)
:_parent(NULL)
, _left(NULL)
, _right(NULL)
, _col(RED)
, _key(key)
, _value(value)
{}
};
三.Insert接口
1.插入节点,依据规则调节颜色。
2.调节颜色,分为三种情况。
<span style="font-size:14px;">bool Insert(const K& key, const V& value)
{
if (_root == NULL) //没有结点的情况
{
_root = new Node(key, value);
_root->_col = BLACK; //一定要改变颜色,因为默认插入结点的颜色为红色,否则底下改变颜色的时候将会没有组父结点而崩溃
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;
}
}
if (parent->_key > key) //插入结点
{
cur = new Node(key,value);
parent->_left = cur;
cur->_parent = parent;
}
else
{
cur = new Node(key, value);
parent->_right = cur;
cur->_parent = parent;
}
while (cur != _root && parent->_col == RED) //调节颜色 条件1:保证一定会有父亲结点 条件2:保证一定会有祖父结点
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left) //确定uncle节点在祖父节点的左/右
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED) //情况1
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
/*if (parent->_left == cur)
{
parent->_col = BLACK;
grandfather->_col = RED;
_RotateR(grandfather);
}
else
{
parent->_col = BLACK;
grandfather->_col = RED;
_RtateL(parent);
}*/
if (parent->_right == cur) //情况3 直接转化为情况2
{
_RotateL(parent);
}
parent->_col = BLACK;
grandfather->_col = RED;
_RotateR(grandfather); //情况2
break;
}
}
else </span><span style="font-size:10px;">//<span style="font-family: Arial, Helvetica, sans-serif;">parent == grandfather->_right 同样分三种情况</span></span><span style="font-size:14px;">
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
if (parent->_left == cur)
{
_RotateR(parent);
}
parent->_col = BLACK;
grandfather->_col = RED;
_RotateL(grandfather);
break;
}
}
}
_root->_col = BLACK;
}</span>
四.Check接口
bool Check()
{
int blacknum = 0;//记录一条路径(这里计算的是最左路)黑色节点的个数
int blacknumcur = 0; //记录当前结点到根节点之间的黑色节点个数
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
++blacknum;
}
cur = cur->_left;
}
return _Check(_root, blacknum, blacknumcur);
}
bool _Check(Node* root, int blacknum, int blacknumcur)
{
if (root == NULL)
{
return true;
}
if (root->_col == BLACK)
{
++blacknumcur;
}
else
{
if (root->_parent && root->_parent->_col == RED) //父亲结点和子结点同为红色
{
cout << "Not balance! ALL RED" << root->_key <<endl;
return false;
}
}
if (root->_left == NULL && root->_right == NULL)
{
if (blacknum == blacknumcur)
{
return true;
}
else //黑色数量不等
{
cout << "Not balance!" << root->_key <<endl;
return false;
}
}
return _Check(root->_left, blacknum, blacknumcur) && _Check(root->_right, blacknum, blacknumcur); //递归求每条路径
}
五.代码实现
#pragma once
#include<iostream>
using namespace std;
enum color
{
RED,
BLACK,
};
template<class K,class V>
struct RBTreeNode
{
RBTreeNode<K, V>* _parent;
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
color _col;
K _key;
V _value;
RBTreeNode(const K& key, const V& value)
:_parent(NULL)
, _left(NULL)
, _right(NULL)
, _col(RED)
, _key(key)
, _value(value)
{}
};
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 = BLACK;
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;
}
}
if (parent->_key > key)
{
cur = new Node(key,value);
parent->_left = cur;
cur->_parent = parent;
}
else
{
cur = new Node(key, value);
parent->_right = cur;
cur->_parent = parent;
}
while (cur != _root && parent->_col == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
/*if (parent->_left == cur)
{
parent->_col = BLACK;
grandfather->_col = RED;
_RotateR(grandfather);
}
else
{
parent->_col = BLACK;
grandfather->_col = RED;
_RtateL(parent);
}*/
if (parent->_right == cur)
{
_RotateL(parent);
}
parent->_col = BLACK;
grandfather->_col = RED;
_RotateR(grandfather);
break;
}
}
else
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
if (parent->_left == cur)
{
_RotateR(parent);
}
parent->_col = BLACK;
grandfather->_col = RED;
_RotateL(grandfather);
break;
}
}
}
_root->_col = BLACK;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool Check()
{
int blacknum = 0;//记录一条路径(这里计算的是最左路)黑色节点的个数
int blacknumcur = 0; //记录当前结点到根节点之间的黑色节点个数
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
++blacknum;
}
cur = cur->_left;
}
return _Check(_root, blacknum, blacknumcur);
}
protected:
bool _Check(Node* root, int blacknum, int blacknumcur)
{
if (root == NULL)
{
return true;
}
if (root->_col == BLACK)
{
++blacknumcur;
}
else
{
if (root->_parent && root->_parent->_col == RED)
{
cout << "Not balance! ALL RED" << root->_key <<endl;
return false;
}
}
if (root->_left == NULL && root->_right == NULL)
{
if (blacknum == blacknumcur)
{
return true;
}
else
{
cout << "Not balance!" << root->_key <<endl;
return false;
}
}
return _Check(root->_left, blacknum, blacknumcur) && _Check(root->_right, blacknum, blacknumcur);
}
void _InOrder(Node* root)
{
if (root == NULL)
return;
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
void _RotateL(Node*& parent)
{
Node* subR = parent->_right;
Node* subRleft = subR->_left;
parent->_right = subRleft;
if (subRleft)
{
subRleft->_parent = parent;
}
subR->_left = parent;
subR->_parent = parent->_parent;
parent->_parent = subR;
parent = subR;
if (parent->_parent == NULL)
{
_root = parent;
}
else
{
Node* ppNode = parent->_parent;
if (ppNode->_key > parent->_key)
{
ppNode->_left = parent;
}
else
{
ppNode->_right = parent;
}
}
}
void _RotateR(Node*& parent)
{
Node* subL = parent->_left;
Node* subLright = subL->_right;
parent->_left = subLright;
if (subLright)
subLright->_parent = parent;
subL->_right = parent;
subL->_parent = parent->_parent;
parent->_parent = subL;
parent = subL;
if (parent->_parent == NULL)
{
_root = parent;
}
else
{
Node* ppNode = parent->_parent;
if (ppNode->_key > parent->_key)
{
ppNode->_left = parent;
}
else
{
ppNode->_right = parent;
}
}
}
protected:
Node* _root;
};
void TestRBTree()
{
int a[] = { 1, 4, 6, 8, 0, 2, 3, 5, 9, 7 };
RBTree<int, int> rb;
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
rb.Insert(a[i], i);
}
rb.InOrder();
rb.Check();
}
以上就是本人在学习过程中的一些经验总结。当然,本人能力有限,难免会有纰漏,希望大家可以指正。