红黑树与二叉搜索树类似
它在每个节点增加了一个存储位记录节点的颜色,可以是RED,也可以是BLACK;通过任意一条从根到叶子简单路径上颜色的约束,红黑树保证最长路径不超过最短路径的二倍,因而近似平衡(最短路径就是全黑节点,最长路径就是一个红节点一个黑节点,当从根节点到叶子节点的路径上黑色节点相同时,最长路径刚好是最短路径的两倍)。它同时满足以下特性:
1.节点是红色或黑色
2.根是黑色
3.叶子节点(外部节点,空节点)都是黑色,这里的叶子节点指的是最底层的空节点(外部节点),下图中的那些null节点才是叶子节点,null节点的父节点在红黑树里不将其看作叶子节点
红色节点的子节点都是黑色
4.红色节点的父节点都是黑色
5.从根节点到叶子节点的所有路径上不能有 2 个连续的红色节点
6.从任一节点到叶子节点的所有路径都包含相同数目的黑色节点
现在我们进行对红黑数的插入
enum Colour
{
BLACK,
RED,
};
template<class K, class V>
class RBTreeNode
{
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
pair<K, V>_kv;
Colour _col;
};
template<class K, class V>
class RBtree
{
typedef RBTreeNode<K, V>Node;
public:
bool Insert(const pair<K, V>& kv)
{
//1.按搜索树的规则进行插入
if (!_root)
{
_root = new Node(kv);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_kv.first<kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(kv);
if (parent->_kv.first < kv.first)
{
parent->_right=cur;
cur->_parent = parent;
}
else
{
parent->left = cur;
cur->_parent=parent;
}
//新增节点红的
cur->_col = RED;
while (parent->_col == RED)
{
//红黑树的调节关键看父节点的另一个节点
Node* grandfather = parent->_parent;
if (grandfather->_left == parent)
{
Node* uncle = grandfather->_right;
//情况一:uncle存在且为红
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
//继续往上处理
cur = grandfather;
parent = cur->_parent;
}
//情况二:uncle不存在或为黑
else
{
//情况三:双旋—>单旋
if (cur==parent->_right)
{
RotateL(parent);//左旋
swap(parent, cur);
}
RotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
break;
}
}
else
{
Node* uncle = grandfather->_right;
//情况一:uncle存在且为红
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
//继续往上处理
cur = grandfather;
parent = cur->_parent;
}
//情况二:uncle不存在或为黑
else
{
//情况三:双旋—>单旋
if (cur == parent->_right)
{
RotateR(parent);
swap(parent, cur);
}
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
break;
}
}
}
root->_col = BLACK;
return true;
}
private:
Node* _root = nullptr;
};