定义
- 红黑树是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black;通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。
性质
- 每个结点不是红色就是黑色
- 根节点是黑色的
- 如果一个节点是红色的,则它的两个孩子结点是黑色的
- 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
- 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
模拟实现
1)实现基本框架
定义结点
- 采用三叉链表的形式定义树的结点,用pair存放数据,增加表示结点颜色的成员变量,结点默认为红色;
enum Colors{
red,
black
};
template <class K, class V>
struct BRTreeNode{
BRTreeNode<K, V>* _left;
BRTreeNode<K, V>* _right;
BRTreeNode<K, V>* _parent;
pair<K, V> _kv;
Colors _color;
BRTreeNode(const pair<K, V>& kv, Colors color = red)
:_left(nullptr),
_right(nullptr),
_parent(nullptr),
_kv(kv),
_color(color){
}
};
其构造、拷贝构造、赋值重载、析构函数同AVLTree
2)实现基本操作
insert插入操作
- 先找待插入位置,然后插入新结点,控制其性质
- 控制红黑树性质:
- 若其父结点是黑色,不需要处理,插入完成;
- 若其父结点为红色,需要处理,关键是看叔叔结点:
- 情况1:叔叔结点存在且为红色—p、u置黑,g置红;然后继续向上处理
- 情况2:叔叔结点不存在或者为黑色—若cur、p、g在一条直线上,只需要单旋处理;若cur、p、g不在一条直线上,需要进行双旋处理。
pair<node*, bool> insert(const pair<K, V>& kv){
if (_root == nullptr){
_root = new node(kv);
_root->_color = black;
return make_pair(_root, true);
}
node* parent = nullptr;
node* cur = _root;
while (cur != nullptr){
if (kv.first < cur->_kv.first){
parent = cur;
cur = cur->_left;
}
else if (kv.first > cur->_kv.first){
parent = cur;
cur = cur->_right;
}
else{
return make_pair(cur, true);
}
}
node* newnode = new node(kv);
cur = newnode;
if (cur->_kv.first < parent->_kv.first){
parent->_left = cur;
cur->_parent = parent;
}
else{
parent->_right = cur;
cur->_parent = parent;
}
if (parent->_color == black)
return make_pair(cur, true);
while (parent && parent->_color == red){
node* grandparent = parent->_parent;
if (parent == grandparent->_left){
node* uncle = grandparent->_right;
if (uncle && uncle->_color == red){
parent->_color = black;
uncle->_color = black;
grandparent->_color = red;
cur = grandparent;
parent = cur->_parent;
}
else{
if (cur == parent->_left){
RotateR(grandparent);
parent->_color = black;
grandparent->_color = red;
}
else{
RotateL(parent);
RotateR(grandparent);
cur->_color = black;
grandparent->_color = red;
}
break;
}
}
else{
node* uncle = grandparent->_left;
if (uncle && uncle->_color == red){
parent->_color = black;
uncle->_color = black;
grandparent->_color = red;
cur = grandparent;
parent = cur->_parent;
}
else{
if (cur == parent->_right){
RotateL(grandparent);
parent->_color = black;
grandparent->_color = red;
}
else{
RotateR(parent);
RotateL(grandparent);
cur->_color = black;
grandparent->_color = red;
}
break;
}
}
}
_root->_color = black;
return make_pair(newnode, true);
}
find查找、operator[ ]操作同AVLTree
判定是否是RBTree
验证其是否为二叉搜索树
验证其是否为满足红黑树的性质
bool isBalance(){
if (_root == nullptr)
return true;
if (_root->_color != black){
cout << "根结点不是黑色" << endl;
return false;
}
node* cur = _root;
int blacknum = 0;
while (cur != nullptr){
if (cur->_color == black)
blacknum++;
cur = cur->_left;
}
int count = 0;
return _isBalance(_root, blacknum, count);
}
bool _isBalance(node* root, int blackNum, int count){
if (root == nullptr){
if (count != blackNum){
cout << "各路径黑色结点的数目不相等" << endl;
return false;
}
return true;
}
if (root->_color == black)
count++;
node* parent = root->_parent;
if (root->_color == red && parent->_color == red)
return false;
return _isBalance(root->_left, blackNum, count) &&
_isBalance(root->_right, blackNum, count);
}
3)实现其迭代器
template <class T, class Ref, class Ptr>
struct BRIterator{
typedef Ref reference;
typedef Ptr pointer;
typedef BRTreeNode<T> node;
typedef BRIterator<T, Ref, Ptr> self;
node* _pnode;
BRIterator(node* node)
:_pnode(node){
}
self& operator++(){
if (_pnode->_right != nullptr){
node* cur = _pnode->_right;
while (cur->_left != nullptr){
cur = cur->_left;
}
_pnode = cur;
}
else{
node* cur = _pnode;
node* parent = cur->_parent;
while (parent && parent->_right == cur){
cur = parent;
parent = parent->_parent;
}
_pnode = parent;
}
return *this;
}
self& operator--(){
if (_pnode->_left != nullptr){
node* cur = _pnode->_left;
while (cur->_right != nullptr){
cur = cur->_right;
}
_pnode = cur;
}
else{
node* cur = _pnode;
node* parent = cur->_parent;
while (parent && cur == parent->_left){
cur = parent;
parent = parent->_parent;
}
_pnode = parent;
}
return *this;
}
Ref operator*(){
return _pnode->_data;
}
Ptr operator->(){
return &_pnode->_data;
}
bool operator!=(const self& s){
return _pnode != s._pnode;
}
bool operator==(const self& s){
return _pnode == s._pnode;
}
};