1.红黑树的性质
1.每个节点只有红色和黑色两种形态
2.根节点是黑色的
3.如果一个节点是红色的,那么它的两个孩子是黑色的,也就是一条路径不存在连续的红色节点
4.对于每个节点,从该节点到其后代的简单路径上均包含数目相同的黑色节点
5.每个空节点都是黑色的
6.最长路径的节点不超过最短的两倍(最短为纯黑节点)
2.红黑树的插入
插入一般选择红色节点,因为黑色就会破坏股则4,但是红色不一定破坏规则3,因为可以插到黑色节点的下面
将插入时的红黑树推断为以上形式,g祖父节点,p父亲节点,u叔叔节点,cur自己
情况1:g黑,pu红,cur红
解决方法:g改成红,pu改成黑,把g当成cur继续向上调整(g如果是根节点就改回来)
情况2:g黑p红u黑或不存在cur红,g,p,cur为左侧的一个路径
解决方法:先对g进行右单旋,p变黑,g变红
情况3:与情况2相同,只不过cur是p的右孩子
解决方法:左单旋
情况4:cur,p为红g,u为黑(u可以不存在),g,pcur是右侧路径
解决方法:对g进行左单旋,p变黑g变红
情况5:同情况4,只不过cur是p的左孩子
解决方法:先右单旋变成情况4,再解决情况4
#include<iostream>
using namespace std;
enum Color
{
RED,
BLACK
};
template<class K, class V>
struct RBTreeNode
{
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
pair<K, V> _kv;
Color _col;
RBTreeNode(pair<K, V>& kv = pair<K, V>())
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, _col(RED)
};
template<class K, class V>
class RBTree
{
protected:
typedef RBTreeNode<K, V> Node;
public:
bool Insert(pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(val);
_root->_col = BLACK;//根肯定是黑色的
return true;
}
else
{
Node* cur = _root;
Node* parent = nullptr
while (cur)
{
parent = cur;
if (cur->_val > val)
cur = cur->left;
else if (cur->_val < val)
cur = cur->_right;
else
return false;
}
cur = new Node(val);
if (parent->_val.first > cur->_val.first)
{
parent->_left = cur;
}
else
{
parent->_parent = cur;
}
cur->_parent = parent;
///从此处开始进行插入后的调整
while (parent && parent->_col == RED)//出问题了
{
Node* grandparent = parent->_parent;
Node* uncle = nullptr;
if (grandparent->_left == parent)//找叔叔分情况
uncle = grandparent->_right;
else
uncle = grandparent->_left;
if (uncle && uncle->_col == RED)//叔叔是红色的,变色
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;
cur = grandparent;
parent = cur->_parent;
}
else if (grandparent->_left == parent)//叔叔是黑色或者不存在,且p是左侧路径,第二
{
if (parent->_left = cur)
{
RotateR(grandparent);
grandparent->_col = RED;
parent->_col = BLACK;
}
else//此时p是右侧路径是情况3
{
RotateL(parent);
RotateR(grandparent);
grandparent->_col = RED;
cur->_col = BLACK;
}
}
else//叔叔是黑色或者不存在,且p是右侧路径
{
if (parent->_right = cur)//情况4
{
RotateL(grandparent);
grandparent->_col = RED;
parent->_col = BLACK;
}
else//情况5
{
RotateR(parent);
RotateL(grandparent);
grandparent->_col = RED;
cur->_col = BLACK;
}
}
void RotateL(RBTNode * parent)//左旋
{
Node* grandparent = parent->_parent;
Node* ChildR = parent->_right;
if (grandparent)
{
if (grandparent->_left == parent)
grandparent->_left = ChildR;
else
grandparent->_right = ChildR;
}
else
_root = ChildR;
ChildR->_parent = grandparent;
parent->_right = ChildR->_left;
ChildR->_left->_parent = parent;
ChildR->_left = parent;
parent->_parent = ChildR;
}
void RotateR(RBTNode * parent)//右旋
{
Node* grandparent = parent->_parent;
Node* ChildL = parent->_left;
if (grandparent)
{
if (grandparent->_left == parent)
grandparent->_left = ChildL;
else
grandparent->_right = ChildL;
}
else
_root = ChildL;
ChildL->_parent = grandparent;
//两两一组进行改变
parent->_left = ChildL->_right;
ChildL->_right->_parent = parent;
ChildL->_right = parent;
parent->_parent = ChildL;//
}
}
}
}
protected:
Node* _root;
};
3.验证红黑树
void Inorde(RBTNode * root, vector<pair<K, V>>&v)
{
if (root == nullptr)
return;
Inorde(root->_left, v);
v.push_back(root->_val);
Inorde(root->_right, v);
}
检查是否是二叉搜索树
检验性质
bool IsBalance(Node*root)
{
//空树也是红黑树
if (root == nullptr)
return true;
//违反性质2
if (root->_col == RED)
{
cout << "树的根节点应该是黑色,可该树却是红色" << endl;
return false;
}
//计算一条路径黑节点数量
Node* cur = root;
int num = 0;
while (cur)
{
if (cur->_col == BLACK)
num++;
cur = cur->_left;
}
return _IsBlance(root,0,num);
}
_IsBalance(Node* root, size_t num, size_t cur_num)
{
if (root == nullptr)
{
//违反性质4
if (num != cur_num)
{
cout << "对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点,但该树却不是" << endl
return false;
}
else
return true;
}
if (root->_col == BLACK)
num++;
//违反性质3
if (root->_parent && root->_parent == RED && root->_col == RED)
{
cout << "如果一个节点是红色的,则它的两个孩子结点是黑色的,可该树却出现了连续的红色节点" << endl;
return false;
}
return IsBalance(root->_left, num, cur_num) && IsBalance(root->_right, num, cur_num);
}