红黑树
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出2倍,因而是接近平衡的 .
红黑树的性质
1.每个结点不是红色就是黑色
2.根节点是黑色的
3.如果一个节点是红色的,则它的两个孩子结点是黑色的
4.对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
5.每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
红黑树新节点的插入
1.按照搜索树的插入方法先插入到合适的叶子节点(插入的点默认红色)
2.根据红色节点是否连续,判断是否需要调整
如果需要调整:
cur是插入的节点
父节点p:指向cur的父节点
祖父节点g:指向p的父节点
叔叔节点u:g的另外一个孩子节点
先看p节点在g节点的那一边
(1)p在祖父节点左边, g->left == p;
再分为3种情况分别处理
<1>叔叔节点u存在且为红
将p,u改成黑色
g改成红色(g如果是根节点,最后在变成黑色)
cur= g继续向上调整
<2>u不存在/存在且是黑色
先看cur节点是否跟p节点一样在左边
不在就先调整cur:以p为轴,左旋
swap(cur,p)交换这俩的指向,再进行下一步
<3>右旋,以g为轴
p调整为黑,g调整为红
结束调整
(2)p在祖父节点的右边,g->right == p;
<1>叔叔节点u存在且为红
将p,u改成黑色
g改成红色(g如果是根节点,最后在变成黑色)
cur= g继续向上调整
<2>u不存在/存在且是黑色
先看cur节点是否跟p节点一样在右边
if(cur==p->left)
不在就先调整cur:以p为轴,右旋
swap(cur,p)交换这俩的指向,再进行下一步
<3>左旋,以g为轴
p调整为黑,g调整为红
结束调整
#include <iostream>
#include <utility>
using namespace std;
//节点的颜色
enum Color
{
BLACK,
RED
};
//红黑树的定义
template<class k, class v>
struct RBNode
{
pair<k, v> _value;
Color _color;
RBNode<k, v>* _parent;
RBNode<k, v>* _left;
RBNode<k, v>* _right;
//默认构造,新插入节点颜色默认红色
RBNode(const pair<k, v>& value = pair<k, v>())
:_value(value)
, _color(RED) //
, _parent(nullptr)
, _left(nullptr)
, _right(nullptr)
{}
};
template<class k, class v>
class RBTree
{
public:
typedef RBNode<k, v> Node;
//头节点,指向根节点,头节点的左/右指向树的最左/最右节点
RBTree()
:_header(new Node)
{
_header->_left = _header->_right = _header;
}
//中序遍历
void inorder()
{
_inorder(_header->_parent);
cout << endl;
}
void _inorder(Node* root)
{
if (root)
{
_inorder(root->_left);
cout << root->_value.first << " ";
_inorder(root->_right);
}
}
//右旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
subL->_right = parent;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
if (parent == _header->_parent)
{
_header->_parent = subL;
subL->_parent = _header;
}
else
{
Node* g = parent->_parent;
subL->_parent = g;
if (g->_left == parent)
g->_left = subL;
else
g->_right = subL;
}
parent->_parent = subL;
}
//左旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
subR->_left = parent;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
if (parent == _header->_parent)
{
_header->_parent = subR;
subR->_parent = _header;
}
else
{
Node* g = parent->_parent;
subR->_parent = g;
if (g->_left == parent)
g->_left = subR;
else
g->_right = subR;
}
parent->_parent = subR;
}
//节点插入
bool insert(const pair<k, v>& val)
{
//空树
if (_header->_parent == nullptr)
{
//创建第一个根节点
Node* root = new Node(val);
//根节点为黑色
root->_color = BLACK;
_header->_parent = root;
root->_parent = _header;
_header->_left = root;
_header->_right = root;
return true;
}
//非空树
//按照搜索树插入方式插入
Node* cur = _header->_parent;
Node* parent = nullptr;
while (cur) {
parent = cur;
if (cur->_value.first == val.first) {
return false;
}
else if (cur->_value.first > val.first) {
cur = cur->_left;
}
else {
cur = cur->_right;
}
}
cur = new Node(val);
if (parent->_value.first < val.first) {
parent->_right = cur;
}
else {
parent->_left = cur;
}
cur->_parent = parent;
// 调整: 修改颜色, 旋转
while (cur != _header->_parent && cur->_parent->_color == RED) {
Node* p = cur->_parent;
Node* g = p->_parent;
//p节点在g节点的左边
if (g->_left == p) {
Node* u = g->_right;
//u存在且为红
if (u && u->_color == RED) {
//修改颜色
u->_color = p->_color = BLACK;
g->_color = RED;
//继续向上查看
cur = g;
}
else {
//u不存在/u存在且为黑
//cur
if (cur == p->_right) {
RotateL(p);
swap(cur, p);
}
//cur在p的左边,右旋
RotateR(g);
//修改颜色
p->_color = BLACK;
g->_color = RED;
break;
}
}
//p节点在g节点的右边
else {
Node* u = g->_left;
//u存在且为红
if (u && u->_color == RED)
{
//修改颜色
u->_color = p->_color = BLACK;
g->_color = RED;
//继续向上查看
cur = g;
}
else
{
//u不存在/u存在且为黑
if (cur == p->_left)
{
RotateR(p);
swap(cur, p);
}
//cur在p的左边,右旋
RotateL(g);
//修改颜色
p->_color = BLACK;
g->_color = RED;
break;
}
}
}
//根颜色置为黑色
_header->_parent->_color = BLACK;
//更新_header的左,右
_header->_left = leftMost();
_header->_right = rightMost();
return true;
}
//最左节点
Node* leftMost()
{
Node* cur = _header->_parent;
while (cur && cur->_left) {
cur = cur->_left;
}
return cur;
}
//最右节点
Node* rightMost()
{
Node* cur = _header->_parent;
while (cur && cur->_right)
cur = cur->_right;
return cur;
}
private:
Node* _header;
};
void testRBTree()
{
RBTree<int, int> rbt;
rbt.insert(make_pair(1, 1));
rbt.insert(make_pair(2, 1));
rbt.insert(make_pair(3, 1));
rbt.insert(make_pair(4, 1));
rbt.insert(make_pair(5, 1));
rbt.insert(make_pair(0, 1));
rbt.insert(make_pair(9, 1));
rbt.insert(make_pair(8, 1));
rbt.insert(make_pair(7, 1));
rbt.insert(make_pair(6, 1));
rbt.inorder();
}
int main() {
testRBTree();
return 0;
}