红黑树的性质
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个孩子结点必须是黑色的
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
5. NIL结点都是黑色的
//模拟实现红黑树
#include
using namespace std;
enum Color
{
RED,
Black
};
template
struct RBTreeNode
{
RBTreeNode
RBTreeNode
RBTreeNode
pair
Color _col;
RBTreeNode()
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(nullptr)
, _col(RED)
{}
};
template
class RBTree
{
typedef RBTreeNode
public:
bool checkColor(Node* root,int blackment ,int benchmark) //检查是否存在连续的红色结点
{
if (root == nullptr)
{
if (blackment != benchmark)
{
return false;
}
return true;
}
if (root->_col == Black)
{
benchmark++;
}
if (root->_col == RED && root->_parent && root->_parent->_col == RED)
{
cout << root->_kv.first << "其父亲出现了连续的红色结点" << endl;
return false;
}
return checkColor(root->_left,blackment,benchmark) && checkColor(root->_right, blackment, benchmark);
}
//检查路径黑色结点的数量 遍历查找所有叶子结点,根据叶子结点的值,将路线走一遍统计黑色节点的数量 2N
//遍历:找到所有叶子结点,
bool isBalance()
{
return _isBalance();
}
bool _isBalance()
{
int benchmark = 0;
//单条路径上的所有黑色结点
Node* cur = _root;
if (cur)
{
if (cur->_col == Black)
{
benchmark++;
}
cur = cur->_left;
}
return checkColor(_root,0,benchmark);
}
void RotateL(Node*& parent) //左单旋 调整父子节点树中顺序,建立链接(parent与cur,parent的parent与cur),调整平衡因子
{
Node* cur = parent->_right;
Node* cur_left = cur->_left;
parent->_right = cur_left;//将cur的左节点放入parent的右结点
if (cur_left)
{
cur_left->_parent = parent; //cur_left控制_parent
}
cur->_left = parent;//将parent放入cur的左节点
Node* ppNode = parent->_parent;
cur->_parent = parent->_parent; //cur的父节点为原parent的父亲
parent->_parent = cur; //parent的父节点为cur
if (parent == _root) //建议原先父节点的父节点与cur的链接
{
_root = cur;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = cur;
}
else
{
ppNode->_right = cur;
}
}
}
void RotatelR(Node*& parent) //右单旋 调整父子节点树中顺序,建立链接(cur_right(?空)与parent,parent与cur,parent的parent(root?)与cur),调整平衡因子
{
Node* cur = parent->_left;
Node* cur_right = cur->_right;
parent->_left = cur_right;//1:将cur的右节点放入parent的左结点
if (cur_right)
{
cur_right->_parent = parent; //cur_right控制_parent
}
cur->_right = parent;//2:将parent放入cur的右节点
Node* ppNode = parent->_parent;
cur->_parent = parent->_parent; //cur的父节点为原parent的父亲
parent->_parent = cur; //parent的父节点为cur
if (parent == _root) //建议原先父节点的父节点与cur的链接
{
_root = cur;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = cur;
}
else
{
ppNode->_right = cur;
}
}
}
void RotatelRL(Node*& parent) //预处理右旋+左单旋
{
Node* cur = parent->_right;
Node* cur_left = cur->_left;
RotatelR(parent->_right);
RotateL(parent);
}
void RotatelLR(Node*& parent) //预处理左单旋+右旋
{
Node* cur = parent->_left;
Node* cur_right = cur->_right;
RotateL(cur);
RotatelR(parent);
}
bool insert(const pair
{
if (_root == nullptr)
{
_root = new Node(kv);
_root->_col = Black;
return true;
}
//插入数据
Node* cur = _root;
Node* parent = cur;
while (cur)
{
parent = cur;
if (kv.first == cur->_kv.first)
{
return false;
}
else if (kv.first > cur->_kv.first)
{
cur = cur->_right;
}
else if (kv.first < cur->_kv.first)
{
cur = cur->_left;
}
}
cur = new Node(kv);
cur->_col = RED;
if (parent->_kv.first < kv.first)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
//1->插入新的结点cur为红色结点,如果其父亲parent是黑色结点直接true
if (parent && parent->_col == Black) return true;
//2->父亲是红色结点,爷爷一定为黑色结点,将爷爷节点变成红色,父亲节点变成黑色,叔叔结点变成黑色,爷爷继续向上查找;
//2->父亲是红色结点,爷爷一定为黑色结点,将爷爷节点变成红色,父亲节点变成黑色,当叔叔结点存在且为黑色的时候,叔叔路线多了黑色结点,叔叔结点这一路线损失去一个黑节点,将parent红节点旋转变黑向上;
//2->父亲是红色结点,爷爷一定为黑色结点,将爷爷节点变成红色,父亲节点变成黑色,当叔叔结点不存在的时候,以上操作会使得叔叔结点这一路线损失去一个黑节点,此时需要根据情况进行旋转
//2.1 -> 向上查找,爷爷是根直接true ---- 爷爷cur ,爷爷的父亲为parent,重复1,2操作
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent; //爷爷
Node* uncle = nullptr;
grandfather->_left == parent ? uncle = grandfather->_right : uncle = grandfather->_left; //叔叔
if (uncle && uncle->_col == RED) //叔叔存在且为红色,叔叔结点变成黑色
{
grandfather->_col = RED;
parent->_col = uncle->_col = Black;
cur = grandfather; //继续向上处理
parent = grandfather->_parent;
continue;
}
if (uncle == nullptr || uncle && uncle->_col == Black)//叔叔结点不存在 或者 叔叔结点存在且为黑色 旋转+变色
{
//四种旋转情况
if (uncle == grandfather->_right) //叔叔在右边
{
if (cur == parent->_left)
{
RotatelR(grandfather);
parent->_col = Black; grandfather->_col = RED;
break;
}
else if (cur == parent->_right)
{
RotatelLR(grandfather);
cur->_col = Black; grandfather->_col = RED;
break;
}
}
else if (uncle == grandfather->_left) //叔叔在左边
{
if (cur == parent->_right)
{
RotatelL(grandfather);
parent->_col = Black; grandfather->_col = RED;
break;
}
else if (cur == parent->_right)
{
RotatelRL(grandfather);
cur->_col = Black; grandfather->_col = RED;
break;
}
}
}
}
_root->_col = Black;
return true;
}
private:
Node* _root=nullptr;
};
int main()
{
return 0;
}