RBTree:是一棵二叉搜索树,每个节点增加一个存储位来表示节点的颜色,通过任何一条路径的从根节点到叶子简单路径上的颜色来约束,红黑树保证了最长路径不超过最短路径的两倍,因而近乎平衡。
RBTree满足的性质:1.每个节点的颜色不是黑色就是红色
2.跟节点的颜色一定是黑色
3.如果一个节点是红色的,则他的两个子节点是黑色的,即没有连续的红节点
4.对每个节点,从该节点到其所有后代叶子结点的简单路径上,均包含相同数目的黑色节点,即 每条路径的黑色节点数目相同
当满足上述的性质时,红黑树自然可以保证最长的路径不超过最短路径的两倍,因为最长的路径一定是在每个黑节点后面跟了一个红节点,而最短路径一定只有黑色节点,这样就保证了上述的结论。
最长路径:黑->红->黑->红->黑->红
最短路径:黑->黑->黑
为了满足上述的性质,我们再插入时,选择每次都默认插入的是红色的节点,因为我们不想破坏第四条性质,因为维护起来相当的麻烦,当你变了一条路径的黑色节点数目是有可能整棵树都要做出调整,因为你改变的这条路径可能是一条子树,那么就很麻烦了,你需要把其他所有路径的都要改变黑色数目来维护这条性质,这样的工作实在是很难,需要注意很多的地方。但是我们插入默认是红色节点也会破坏它的第三条性质,但是这里第三条的性质比起第四条还是简单了许多的,所以我们选择破坏第三条,而不是第四条。这时当我们插入红节点时就可能会出现连续的红节点这样的情况,这里我们需要做出调整来满足其第三条性质。下面是其几种情况:
第一种情况:grandfather为黑,parent为红,uncle存在且为红,这时我们需要将parent和uncle变黑,再grandfather变1红,这样就没有连续的红色节点,同时使这棵树的黑色节点数没有改变,这样就很好的使这棵RBTree得到了维护,但是我们还需要向上调整,因为这棵树keen那个只是一颗子树。
第二种情况:cur为红,parent为红,grandfather为黑,uncle存在且为黑或者uncle不存在,parent为grandfather的左孩子,cur也是parent的左孩子,则这时需要以grandfather为轴进行一个右单旋,同时将parent变为黑grandfather变为红,这样黑色的节点数目还是没有改变的。
uncle存在且为黑或者uncle不存在的情况:
第三种情况:其实第二种可以说是第三种的一种特殊情况,也就是AVL的双旋和单选的问题,cur为红,parent为红,grandfather为黑,uncle存在且为黑或者uncle不存在,parent是grandfather的左孩子,cur是parent的有孩子,这是就是一双旋,现以parent为轴进行左单选,不调整颜色,再以grandfather为轴进行右单旋,同样的parent变为黑色,grandfather变为红色。
上面就是RBTree破坏第三条维持第四条之后的调整部分。
下面是我的代码部分:
#pragma once
#include<iostream>
using namespace std;
enum Color
{
RED,
BLEAK,
};
template<class K,class V>
struct RBTreeNode
{
K _key;
V _value;
Color _col;
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
RBTreeNode(const K& key, const V& value)
:_left(NULL)
, _right(NULL)
, _parent(NULL)
, _key(key)
, _value(value)
, _col(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->_col = BLEAK;
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就是我们要找到的位置
cur = new Node(key,value);
if (parent->_key > key)
{
parent->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}
//到了这里我们已经插入了节点,这里开始判断是不是RBTree
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
//如果parent是grandfather的左,那么uncle是grandfather的右
if (parent == grandfather->_left)
{
Node *uncle = grandfather->_right;
if (uncle && uncle->_col == RED) //叔叔存在且为红
{
grandfather->_col = RED;
parent->_col = uncle->_col = BLEAK;
cur = grandfather;
parent = cur->_parent;
}
else //叔叔不存在/存在是黑色的
{
if (cur == parent->_right)
{
RotateL(parent);
swap(parent, cur);
}
RotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLEAK;
break;
}
}
else //parent=grandfather->_right
{
Node *uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
grandfather->_col = RED;
parent->_col = uncle->_col = BLEAK;
cur = grandfather;
parent = cur->_parent;
}
else //叔叔不存在/存在是黑色的
{
if (cur == parent->_left)
{
RotateR(parent);
swap(parent,cur);
}
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLEAK;
break;
}
}
}
//在调整后最后可能把根节点变红,所以我们在所有操作做完后,我们最后将root变为黑色
_root->_col = BLEAK;
return true;
}
//右单旋
void RotateR(Node *cur)
{
Node *parent = cur->_parent;
Node *subL = cur->_left;
Node *subLR = subL->_right;
if (cur == _root)
{
_root = subL;
subL->_parent = NULL;
subL->_right = cur;
}
else
{
if (cur == parent->_left)
{
parent->_left = subL;
}
else
{
parent->_right = subL;
}
subL->_parent = parent;
subL->_right = cur;
}
cur->_parent = subL;
cur->_left = subLR;
if (subLR)
subLR->_parent = cur;
}
//左单选
void RotateL(Node *cur)
{
Node* parent = cur->_parent;
Node* subR = cur->_right;
Node *subRL = subR->_left;
//当cur==_root
if (cur == _root)
{
_root = subR;
subR->_parent = NULL;
subR->_left = cur;
}
else //这时候有parent了
{
if (parent->_left == cur)
{
parent->_left = subR;
}
else
{
parent->_right = subR;
}
subR->_parent = parent;
subR->_left = cur;
}
cur->_right = subRL;
cur->_parent = subR;
if (subRL)
subRL->_parent = cur;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void _InOrder(Node* root)
{
if (root == NULL)
{
return;
}
_InOrder(root->_left);
//cout << root->_key << "->" << root->_value << " ";
cout << root->_key <<" ";
_InOrder(root->_right);
}
bool Isbalance()
{
size_t k = 0;
size_t blackNum = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLEAK)
++k;
cur = cur->_left;
}
return _Isbalance(_root,blackNum,k);
}
bool _Isbalance(Node *root, size_t blackNum, const size_t k) //这里blackNum不能给引用
{
//判断黑色节点是否相同
if (root == NULL) //这里是找到空节点,不是叶子节点
{
if (blackNum == k)
{
return true;
}
else
{
cout << "黑色节点的个数不相同"<<endl;
return false;
}
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "连续的红节点" << endl;
return false;
}
if (root->_col == BLEAK)
++blackNum;
//跑起来
return( _Isbalance(root->_left,blackNum,k)
&& _Isbalance(root->_right,blackNum,k));
}
protected:
Node* _root;
};
//测试RBTree
void TestRBTree()
{
RBTree<int, int > RBTree;
int a[] = {16,3,7,11,9,26,18,14,15};
//int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
RBTree.Insert(a[i], i);
cout << "RBTree.Isbalence() -> " << RBTree.Isbalance() << endl;
}
//RBTree.Insert(16,1);
//RBTree.Insert(3, 1);
//RBTree.Insert(7, 1);
//RBTree.Insert(11, 1);
//RBTree.Insert(9, 1);
//RBTree.Insert(26, 1);
//RBTree.Insert(18, 1);
//RBTree.Insert(14, 1);
//RBTree.Insert(15, 1);
RBTree.InOrder();
}