1.红黑树的性质
红黑树是一个最长的分支不大于最短分支2倍的一颗平衡搜索数
为了满足这个目标有如下特性:
a.根节点必须是黑色
b.红色结点的双亲必须是黑色结点
c.每条路径上的黑色结点数量相同
d.nil是黑色结点
如图:
2. 红黑数的插入
首先由于1中的特性c的存在,如果我们将新插入的结点的颜色设置为黑色的话会给我们带来很大的麻烦。所以我们要选择红色作为新插入结点的颜色。
我们将新插入的结点叫做cur,cur的父亲结点叫做parent,parent的父亲结点叫做grandfather,grandfather另一个儿子叫做uncle。
插入情况1:(uncle是红色)
此时我们只需要改变parent grandfather uncle的颜色就可以实现调整
插入情况2:(uncle是空或者黑色)
a.当cur parent grandfather 呈现 / 形时对g右旋转,同时将parent grandfather变色
当cur parent grandfather 呈现 \ 形时对g左旋转,同时将parent grandfather变色
b.当cur parent grandfather 呈现 < 形时,先对p左旋转,在对g右旋转,同时将cur grandfather变色。
当cur parent grandfather 呈现 > 形时,先对p右旋转,在对g左旋转,同时cur grandfather变色。
3.代码
using namespace std;
enum colour
{
Red,
Black
};
template<class k,class v>
class RBNode
{
public:
RBNode(const pair<k,v>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
,_kv(kv)
{}
public:
pair<k, v> _kv;
RBNode<k, v>* _left;
RBNode<k, v>* _right;
RBNode<k, v>* _parent;
colour _col;
};
template<class k,class v>
class RBTree
{
typedef RBNode<k,v> Node;
public:
bool Insert(const pair<k, v>& kv)
{
Node* cur = _root; Node* parent = nullptr;
if (_root == nullptr)
{
_root = new Node(kv);
_root->_col = Black;
return true;
}
while (cur)
{
if (kv.first < cur->_kv.first)
{
parent = cur;
cur = cur->_left;
}
else if (kv.first > cur->_kv.first)
{
parent = cur;
cur = cur->_right;
}
else
return false;
}
//找到位置
cur = new Node(kv);
cur->_col = Red; // 设置颜色为红色
if (kv.first < parent->_kv.first)
parent->_left = cur;
else
parent->_right = cur;
cur->_parent = parent;
//如果parent的颜色是黑色就不需要继续处理
while (parent && parent->_col == Red)
{
Node* grandfather = parent->_parent;
assert(grandfather);
assert(grandfather->_col == Black);
Node* uncle = nullptr;
if (grandfather->_left == parent)
uncle = grandfather->_right;
else
uncle = grandfather->_left;
//情况1 只需要变色
if (uncle && uncle->_col == Red)
{
parent->_col = Black;
uncle->_col = Black;
grandfather->_col = Red;
cur = grandfather;
parent = cur->_parent;
}
else
{
//情况2 中 / \ 形状
if (parent->_left == cur && grandfather->_left == parent)
{
RoateR(grandfather);
grandfather->_col = Red;
parent->_col = Black;
break;
}
else if (parent->_right == cur && grandfather->_right == parent)
{
RoateL(grandfather);
grandfather->_col = Red;
parent->_col = Black;
break;
}
//情况2 中 < > 形状
else if (parent->_left == cur && grandfather->_right == parent)
{
RoateR(parent);
RoateL(grandfather);
grandfather->_col = Red;
cur->_col = Black;
break;
}
else
{
RoateL(parent);
RoateR(grandfather);
grandfather->_col = Red;
cur->_col = Black;
break;
}
}
}
_root->_col = Black;
return true;
}
void InOrder()
{
_InOrder(_root);
}
private:
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_kv.first<<" ";
_InOrder(root->_right);
}
//左转
void RoateL(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)
{
if (ppnode->_left == parent)
{
ppnode->_left = subr;
subr->_parent = ppnode;
}
else
{
ppnode->_right = subr;
subr->_parent = ppnode;
}
}
else
{
_root = subr;
subr->_parent = nullptr;
}
}
//右转
void RoateR(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)
{
if (ppnode->_left == parent)
{
ppnode->_left = subl;
subl->_parent = ppnode;
}
else
{
ppnode->_right = subl;
subl->_parent = ppnode;
}
}
else
{
_root = subl;
subl->_parent = nullptr;
}
}
Node* _root=nullptr;
};