红黑树 模拟
#pragma once
#include <utility>
enum Color
{
RED,
BLACK
};
template <typename K, typename V>
struct RBTreeNode
{
RBTreeNode(const pair<K, V>& kv)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_kv(kv)
,_col(RED)
{}
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
pair<K, V> _kv;
Color _col;
};
template <typename K, typename V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
void RotateL(Node* parent)
{
Node* cur = parent->_right;
Node* grandparent = parent->_parent;
if (parent == _root)
{
_root = cur;
}
else
{
if (grandparent->_left == parent)
{
grandparent->_left = cur;
}
else
{
grandparent->_right = cur;
}
}
if (cur->_left != nullptr)
{
cur->_left->_parent = parent;
}
parent->_parent = cur;
parent->_right = cur->_left;
cur->_left = parent;
cur->_parent = grandparent;
}
void RotateR(Node* parent)
{
Node* cur = parent->_left;
Node* grandparent = parent->_parent;
if (parent == _root)
{
_root = cur;
}
else
{
if (grandparent->_left == parent)
{
grandparent->_left = cur;
}
else
{
grandparent->_right = cur;
}
}
if (cur->_right != nullptr)
{
cur->_right->_parent = parent;
}
parent->_parent = cur;
parent->_left = cur->_right;
cur->_parent = grandparent;
cur->_right = parent;
}
void RotateLR(Node* parent)
{
Node* cur = parent->_left;
RotateL(cur);
RotateR(parent);
}
void RotateRL(Node* parent)
{
Node* cur = parent->_right;
RotateR(cur);
RotateL(parent);
}
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
_root->_col = BLACK;
return true;
}
Node* cur = _root;
Node* parent = nullptr;
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 false;
}
}
Node* newnode = new Node(kv);
cur = newnode;
if (kv.first < (parent->_kv).first)
{
newnode->_parent = parent;
parent->_left = newnode;
}
else if (kv.first > (parent->_kv).first)
{
newnode->_parent = parent;
parent->_right = newnode;
}
while (parent != nullptr)
{
Node* grandparent = parent->_parent;
if (grandparent == nullptr)
{
parent->_col = BLACK;
_root = parent;
break;
}
else if (parent->_col == BLACK)
{
break;
}
else if (parent->_col == RED)
{
if (grandparent->_left == parent && grandparent->_right == nullptr)
{
if (parent->_left == cur)
{
RotateR(grandparent);
parent->_col = RED;
grandparent->_col = BLACK;
cur->_col = BLACK;
cur = parent;
parent = parent->_parent;
}
else
{
RotateLR(grandparent);
cur->_col = RED;
grandparent->_col = BLACK;
parent->_col = BLACK;
parent = cur->_parent;
}
}
else if (grandparent->_right == parent && grandparent->_left == nullptr)
{
if (parent->_left == cur)
{
RotateRL(grandparent);
cur->_col = RED;
grandparent->_col = BLACK;
parent->_col = BLACK;
parent = cur->_parent;
}
else
{
RotateL(grandparent);
parent->_col = RED;
grandparent->_col = BLACK;
cur->_col = BLACK;
cur = parent;
parent = parent->_parent;
}
}
else if (grandparent->_left->_col == RED && grandparent->_right->_col == RED)
{
grandparent->_col = RED;
grandparent->_left->_col = BLACK;
grandparent->_right->_col = BLACK;
cur = grandparent;
parent = grandparent->_parent;
}
else if (grandparent->_left == parent && grandparent->_right->_col == BLACK)
{
if (parent->_left == cur)
{
RotateR(grandparent);
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
RotateLR(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
break;
}
else if (grandparent->_right == parent && grandparent->_left->_col == BLACK)
{
if (parent->_left == cur)
{
RotateRL(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
else
{
RotateL(grandparent);
parent->_col = BLACK;
grandparent->_col = RED;
}
break;
}
}
}
if (_root->_col == RED)
{
_root->_col = BLACK;
}
return true;
}
int GetBlackCount()
{
int blackcount = 0;
Node* cur = _root;
while (cur != nullptr)
{
if (cur->_col == BLACK)
{
blackcount++;
}
cur = cur->_left;
}
return blackcount;
}
bool IsRBTree()
{
if (_root == nullptr)
{
return true;
}
if (_root->_col == RED)
{
return false;
}
int blackcount = GetBlackCount();
return _IsRBTree(_root, 0, blackcount);
}
private:
bool _IsRBTree(Node* root, int nowBlackCount, const int blackcount)
{
if (root == nullptr)
{
if (nowBlackCount == blackcount)
{
return true;
}
else
{
return false;
}
}
if (root->_col == BLACK)
{
nowBlackCount++;
}
else if (root->_col == RED)
{
if (root->_left != nullptr && root->_left->_col == RED)
{
return false;
}
if (root->_right != nullptr && root->_right->_col == RED)
{
return false;
}
}
return _IsRBTree(root->_left, nowBlackCount, blackcount) && _IsRBTree(root->_right, nowBlackCount, blackcount);
}
Node* _root = nullptr;
};