这是一颗红黑树
由图可知红黑树的节点分为红节点和黑节点
红黑树规定了每一条路径上的黑节点数量必须相等且不能出现连续的红节点且在红黑树中将空节点拓展为黑节点
红黑树的性质决定了
最短路径的节点数 x 2 >= 最长路径的节点数
在一定程度上控制了树的平衡,相比于AVL树,红黑树对左右子树的高度并没有很严格,大大减少了旋转所带来的成本
下面来实现红黑树的插入功能:
定义红黑树节点
enum Colour
{
RED,
BLACK,
}; //你也可以使用宏定义
//define RED 0
//define BLACK 1
template<class K, class V>
struct RBTreeNode
{
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
pair<K, V> _kv;
Colour _col;
RBTreeNode(const pair<K, V>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _col(RED)
{}
/*之所以默认插入红节点的原因是因为能够更好地调整,如果默认插入
黑节点,那么所有路径都会收到影响,不利于调整*/
};
定义红黑树
template<class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
bool Insert(const pair<K, V>& kv)
{
......
}
private:
Node* _root = nullptr;
};
插入实现
/
/
/
while (parent && parent->_col == RED)
{Node* grandfather = parent->_parent;}
只有当父节点不为空且未红色时才需要进行调整
由于子树调整后颜色的变化可能会对上一层造成影响,需要将已经调整后的子树是做一个整体继续向上调整
————————————————————
只需要将父节点和叔节点变黑,爷节点变红,向上继续调整
if (grandfather->_left == parent)
{
Node* uncle = grandfather->_right;
//u存在且为红,变色处理,并继续往上处理
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
// 继续往上调整
cur = grandfather;
parent = cur->_parent;
}
—————————————————————
此类情况又可以分为两类
i:
ii:
else //u不存在/u存在且为黑,旋转+变色
{
// g
// p u
// c
if (cur == parent->_left)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// g
// p u
// c
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
//parent->_col = RED;
grandfather->_col = RED;
}
break;
}
//只给出部分情况下的代码。
————————————————————————————————————————————————————————————————————————————————————————————————————————————