红黑树是一种二叉搜索树。
每个结点增加一个储存位表示结点的颜色,可以是Red或Black。
其中通过规则对结点着色的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因此保证接近平衡。
enum class Color //结点颜色
{
RED,
BLACK
};
template<class K, class V>
struct RBTreeNode
{
//红黑树结点,默认红色
RBTreeNode(const pair<K, V>& kv)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_kv(kv)
,_color(Color::RED)
{}
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
pair<K, V> _kv;
Color _color; //结点颜色,红色和黑色
};
下面代码是插入根节点和普通节点部分:
template<class K, class V>
class RBTree
{
private:
typedef RBTreeNode<K, V> Node;
public:
bool Insert(const pair <K, V>& kv)
{
//空树直接申请结点
if (_root == nullptr)
{
_root = new Node(kv);
_root->_color = Color::BLACK; //根结点就置为黑色
return true;
}
//1.找到插入位置
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else
{
parent = cur;
cur = cur->_left;
}
}
//2.找到了直接插入
cur = new Node(kv);
if (parent->_kv.first > kv.first)
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent; //记得互联
//3.检查是否满足红黑树,若满足直接退出
//不满足,需要调整红黑树
//....
}
因为插入结点为红色,如果父亲存在且父亲为红色,那么就破坏了规则,需要调整。
//3.检查是否满足红黑树,若满足直接退出
//不满足,需要调整红黑树
while(parent && parent->_color == Color::RED)
{
//...调整
}
该部分是爷爷结点的左子树出问题了,右子树出问题与之类似
**先给出结论:**看叔叔结点的脸色(颜色)行事。
需要注意:如果调整后grandpa的父亲也是红,需要继续向上调整。把grandpa当成新插入的结点即可(cur)。
if (grandfather->_left == parent) //爷爷的左子树出问题了
{
Node* uncle = grandfather->_right;
//情况一: cur 为红,p为红,g为黑, u存在且为红
if (uncle && uncle->_color == Color::RED) // 只需要叔父爷变色即可
{
parent->_color = Color::BLACK;
grandfather->_color = Color::RED;
uncle->_color = Color::BLACK; //子树调整完成
//把爷爷当作新插入结点,继续调整
cur = grandfather;
parent = cur->_parent;
}
2.1 单旋+变色(p、g变色)
2.3 双旋+变色(c、g变色)
代码部分:
else //2.u存在且为黑 3.u不存在 旋转+变色
{
//2 g
// p u
// c
if (cur == parent->_left) //父亲爷爷变色
{
_RotateR(grandfather); //以g为轴点右单旋
parent->_color = Color::BLACK;
grandfather->_color = Color::RED;
}
else //cur是p的右孩子
{
// g
// p u
// c 叔父爷变色
_RotateL(parent);
_RotateR(grandfather);
grandfather->_color = Color::RED;
cur->_color = Color::BLACK;
}
enum class Color //结点颜色
{
RED,
BLACK
};
template<class K, class V>
struct RBTreeNode
{
//红黑树结点,默认红色
RBTreeNode(const pair<K, V>& kv)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_kv(kv)
,_color(Color::RED)
{}
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
pair<K, V> _kv;
Color _color;
};
template<class K, class V>
class RBTree
{
private:
typedef RBTreeNode<K, V> Node;
public:
bool Insert(const pair <K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
_root->_color = Color::BLACK; //根结点就置为黑色
return true;
}
//1.找到插入位置
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else
{
parent = cur;
cur = cur->_left;
}
}
//2.找到了直接插入
cur = new Node(kv);
if (parent->_kv.first > kv.first)
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent; //记得互联
//3.检查是否满足红黑树,若满足直接退出
//不满足,需要调整红黑树
while(parent && parent->_color == Color::RED)
{
//爷爷结点一定存在,因为parent为红,爷爷结点一定为黑!
Node* grandfather = parent->_parent;
if (grandfather->_left == parent)
{
Node* uncle = grandfather->_right;
//情况一: cur 为红,p为红,g为黑, u存在且为红
if (uncle && uncle->_color == Color::RED) // 只需要叔父爷变色即可
{
parent->_color = Color::BLACK;
grandfather->_color = Color::RED;
uncle->_color = Color::BLACK; //子树调整完成
//把爷爷当作新插入结点,继续调整
cur = grandfather;
parent = cur->_parent;
}
else //2.u存在且为黑 3.u不存在 旋转+变色
{
//2 g
// p u
// c
if (cur == parent->_left) //父亲爷爷变色
{
_RotateR(grandfather); //以g为轴点右单旋
parent->_color = Color::BLACK;
grandfather->_color = Color::RED;
}
else //cur是p的右孩子
{
// g
// p u
// c 叔父爷变色
_RotateL(parent);
_RotateR(grandfather);
grandfather->_color = Color::RED;
cur->_color = Color::BLACK;
}
break;
}
}
else //parent = grandfather->_right
{
// g
// u p
// c
Node* uncle = grandfather->_left;
if (uncle && uncle->_color == Color::RED) //情况1 u存在且为红
{
uncle->_color = Color::BLACK;
parent->_color = Color::BLACK;
grandfather->_color = Color::RED;
//继续往上调整
cur = grandfather;
parent = cur->_parent;
}
else //u存在为黑 u不存在
{
// g
// u p
// c
if (cur == parent->_right)
{
//左单旋
_RotateL(grandfather);
parent->_color = Color::BLACK;
grandfather->_color = Color::RED;
}
else
{
// g
// u p
// c
_RotateR(parent);
_RotateL(grandfather);
grandfather->_color = Color::RED;
cur->_color = Color::BLACK;
}
break;
}
}
}
_root->_color = Color::BLACK;
return true;
}
void InOrder()
{
_InOrder(_root);
}
bool IsRBTree()
{
//空树也是红黑树
if (_root == nullptr)
{
return true;
}
if (_root->_color != Color::BLACK)
{
cout << "根节点不是黑色" << endl;
return false;
}
//获取任意一条路径中黑色结点个数
int benchMark = 0;
Node* cur = _root;
while (cur)
{
if (cur->_color == Color::BLACK)
{
benchMark++;
}
cur = cur->_left;
}
return _IsRBTree(_root, 0, benchMark);
}
private:
bool _IsRBTree(Node* root, int blackCount, int benchMark)
{
if (root == nullptr)
{
if (blackCount != benchMark)
{
cout << "黑色结点数量异常" << endl;
return false;
}
return true;
}
if (root->_color == Color::BLACK) //黑节点就计数
{
blackCount++;
}
else //红色结点检查是否满足要求
{
//检查红红
Node* parent = root->_parent;
if (parent && parent->_color == Color::RED)
{
cout << root->_kv.first << "结点不满足红红" << endl;
return false;
}
}
return _IsRBTree(root->_left, blackCount, benchMark) && _IsRBTree(root->_right, blackCount, benchMark);
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << " ";
_InOrder(root->_right);
}
void _RotateR(Node* parent)
{
//右单旋,儿子上位变父亲,父亲被挤到右边
Node* pParent = parent->_parent; //爷爷
Node* childL = parent->_left; //左孩子
parent->_left = childL->_right;
if (childL->_right)
{
childL->_right->_parent = parent; //子指向父
}
childL->_right = parent;
parent->_parent = childL; //子指向父
//最后将chldL指向pParent
childL->_parent = pParent;
if (pParent == nullptr) // childL 变成了根
{
_root = childL;
childL->_parent = nullptr;
}
else
{
if (pParent->_left == parent)
{
pParent->_left = childL;
}
else
{
pParent->_right = childL;
}
}
}
//左单旋
void _RotateL(Node* parent)
{
Node* childR = parent->_right; //存右孩子
parent->_right = childR->_left; //右孩子的左孩子互连父亲
if (childR->_left)
{
childR->_left->_parent = parent;
}
childR->_left = parent; //parent和childR互联
Node* pparent = parent->_parent; //暂存爷爷
parent->_parent = childR;
//爷爷和childR互联
childR->_parent = pparent;
if (pparent == nullptr) //爷爷为空,就是根
{
_root = childR;
childR->_parent = nullptr;
}
else
{
if (pparent->_left == parent)
{
pparent->_left = childR;
}
else
{
pparent->_right = childR;
}
}
}
private:
Node* _root=nullptr; //根
};
// 测试接口
void RBTest1()
{
int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
//int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
RBTree<int, int> t;
for (auto e : a)
{
t.Insert(pair<int, int>(e, 0));
t.InOrder();
cout << endl;
}
t.InOrder();
}
void RBTest2()
{
//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
RBTree<int, int> t;
for (auto e : a)
{
t.Insert(pair<int, int>(e, 0));
t.InOrder();
cout <<t.IsRBTree()<<endl;
}
t.InOrder();
}