RBTree — 红黑树
红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单
路径上的
颜色
来约束,红黑树保证
最长路径不超过最短路径的两倍
,因而近似于平衡。
红黑树是满足下面红黑性质的二叉搜索树
- 每个结点,不是红色就是黑色的
- 根结点是黑色的
- 如果一个结点是红色的,则它的两个子结点是黑色的
- 对每个结点,从该结点到其所有后代的叶子的简单路径上,均包含相同数目的黑色结点。
插入时的几种情况
cur为当前结点,parent为父结点,grandfather为祖父结点,uncle为叔叔结点,
三角形代表是子树或者是空树
。
第一种情况:
cur为红色,parent为红色,grandfather为黑色,uncle存在且为红
则
将parent、uncle改为黑色,grandfather改为红色
,然后把grandfather当成cur,继续向上调整。
![](https://i-blog.csdnimg.cn/blog_migrate/4aed02e4ed794c0798fff95d67ac6904.png)
第二种情况:
cur为红色,parent为红色,grandfather为黑色,uncle不存在/uncle为黑色
parent为grandfather的左孩子,cur为parent的左孩子,则进行右单旋;相反,parent为grandfather的右孩子,cur为parent的右孩子,则进行左单旋
parent、grandfather变色--parent变黑,grandfather变红
uncle为黑色,可以是下面这种情况,cur可能是从下往上调整变成红色的。
左单旋与上面的类似,不会旋转的请看我写的AVL树的博客里有详细的旋转资料。
第三种情况:
cur为红色,parent为红色,grandfather为黑色,uncle不存在/uncle为黑色
parent为grandfather的左孩子,cur为parent的右孩子,则针对parent做左单旋;相反,parent为grandfather的右孩子,cur为parent的左孩子,则针对parent做右单旋,这样就转换成了情况二,要注意转换为情况二之后要交换parent和cur,再进行对parent、grandfather变色。
![](https://i-blog.csdnimg.cn/blog_migrate/b830e7549b79a017b9b04b6c92e24d08.png)
思考:为什么每次要默认插入的是红结点?
因为要保证每条路径上的黑结点数相同,若默认插入黑结点,则每条路径都要改动,则默认插入红结点。
如何判断其是否平衡?
我们先统计其最左结点这条路径上的黑结点数,然后再递归比较其它路径上的黑结点数目是否与最左结点的黑结点数目相同,并要满足红黑树的性质,不能有连续的红结点。
下面是完整代码
enum NodeColor
{
RED,
BLACK
};
template<class K,class V>
struct RBTreeNode
{
RBTreeNode<K, V>* _parent;
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
K _key;
V _value;
NodeColor _color;
RBTreeNode(const K& key, const V& value)
:_parent(NULL)
, _left(NULL)
, _right(NULL)
, _key(key)
, _value(value)
, _color(RED)
{}
};
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->_color = 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;
}
}
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为红,uncle为红
//3.parent为红,uncle不存在/uncle为黑
while (parent && parent->_color == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_color == RED)//uncle存在且为红
{
parent->_color = uncle->_color = BLACK;
grandfather->_color = RED;
//继续向上调节
cur = grandfather;
parent = cur->_parent;
}
else//uncle不存在 或 uncle为黑
{
if (cur == parent->_right)
{
RotateL(parent);
swap(cur, parent);//双旋会导致不是改变p、g的颜色,所以在左旋之后交换cur和parent的颜色
}
RotateR(grandfather);
parent->_color = BLACK;
grandfather->_color = RED;
}
}
else
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_color == RED)
{
parent->_color = uncle->_color = BLACK;
grandfather->_color = RED;
//继续向上调节
cur = grandfather;
parent = cur->_parent;
}
else
{
if (cur == parent->_left)
{
RotateR(parent);
swap(cur, parent);
}
RotateL(grandfather);
parent->_color = BLACK;
grandfather->_color = RED;
}
}
}
_root->_color = BLACK;
return true;
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
//调整指向
subR->_left = parent;
parent->_right = subRL;
if (subRL) //subRL非空
{
subRL->_parent = parent;
}
Node* ppNode = parent->_parent;
if (_root == parent)
{
_root = subR;
subR->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
subR->_parent = ppNode;
}
else
{
ppNode->_right = subR;
subR->_parent = ppNode;
}
}
parent->_parent = subR;
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
subL->_right = parent;
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
Node* ppNode = parent->_parent;
if (_root == parent)
{
_root = subL;
subL->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
subL->_parent = ppNode;
}
else
{
ppNode->_right = subL;
subL->_parent = ppNode;
}
}
parent->_parent = subL;
}
bool IsBanlance()
{
if (_root && _root->_color == RED)
{
return false;
}
int k = 0;
int blacknum = 0;
Node* cur = _root;
while (cur)
{
if (cur->_color == BLACK)
{
++k;
}
cur = cur->_left;
}
return _IsBanlance(_root, k, blacknum);
}
bool _IsBanlance(Node* cur, const int k, int blacknum)
{
if (cur == NULL)
{
if (k != blacknum)
{
cout << "黑结点数不相等" << endl;
return false;
}
return true;
}
if (cur->_color == RED && cur->_parent->_color == RED)
{
return false;
}
if (cur->_color == BLACK)
{
++blacknum;
}
return _IsBanlance(cur->_left, k, blacknum) && _IsBanlance(cur->_right, k, blacknum);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void _InOrder(Node* root)
{
if (root == NULL)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
private:
Node* _root;
};
//测试
void TestRBTree()
{
RBTree<int, int> t1;
int a1[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15};
//int a1[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
for (size_t i = 0; i < sizeof(a1) / sizeof(a1[0]); ++i)
{
t1.Insert(a1[i], i);
cout << a1[i] << "平衡?"<< t1.IsBanlance() << endl;
}
t1.InOrder();
cout << t1.IsBanlance() << endl;
}