红黑树:
1.空树(红黑树可以是空树)
2.非空:二叉搜索树 + 给节点增加颜色(红色和黑色)
红黑树通过其性质的限制可以保证最长节点数不超过最短节点数的2倍
红黑树的性质:
1.红黑树中的每个节点都有颜色,不是红色就是黑色
2.根节点的颜色必须是黑色
3.红色节点的孩子节点必须是黑色节点(不能有两个连续的红色节点)
4.每条路径的黑色节点数必须相等
5.所有“叶子节点”的颜色必须是黑色(可忽略)
注:
本红黑树是模拟实现STL底层的红黑树
在创建红黑树是我们先来看三种特殊的情况
上面是插入到左子树时的节点的情况,如果插入到右子树,则是上述三种情况的反情况
#pragma once
#include <iostream>
using namespace std;
enum Color{RED, BLACK};
template<class T>
struct RBNode
{
RBNode(const T& data = T(), Color c = RED)
:val_(data)
,color_(c)
,parent_(nullptr)
,left_(nullptr)
,right_(nullptr)
{}
T val_;
Color color_;
struct RBNode* parent_;
struct RBNode* left_;
struct RBNode* right_;
};
template<class T>
class RBTree
{
typedef RBNode<T> Node;
public:
RBTree()
{
//创建空树(红黑树可以是空树)
head = new Node();
head->left_ = head;
head->right_ = head;
}
~RBTree()
{
Destory(head->parent_);
}
void InOrder()
{
_InOrder(head->parent_);
cout << endl;
}
bool Insert(const T& data)
{
//1.按二叉搜索树插入节点
Node*& root = GetRoot();
if (nullptr == root)
{
root = new Node(data, BLACK);
root->parent_ = head;
head->left_ = root;
head->right_ = root;
return true;
}
Node* cur = root;
Node* parent = head;
//找到要插入节点的位置
while (cur)
{
parent = cur;
if (data > cur->val_)
cur = cur->right_;
else if (data < cur->val_)
cur = cur->left_;
else
return false;
}
cur = new Node(data);
if (data > parent->val_)
parent->right_ = cur;
else
parent->left_ = cur;
cur->parent_ = parent;
//2.新节点插入后,红黑树的性质3可能被破坏(不能有连续的两个红色节点)
while (parent != head && RED == parent->color_)
{
Node* Grandfather = parent->parent_;
if (parent == Grandfather->left_)
{
Node* uncle = Grandfather->right_;
if (uncle && uncle->color_ == RED)
{
//情况1
parent->color_ = BLACK;
uncle->color_ = BLACK;
Grandfather->color_ = RED;
cur = Grandfather;
parent = cur->parent_;
}
else
{
//情况2和情况3
//情况3
if (cur == parent->right_)
{
RotateLeft(parent);
swap(parent, cur);
}
//情况2
parent->color_ = BLACK;
Grandfather->color_ = RED;
RotateRight(Grandfather);
}
}
else
{
//情况1情况2情况3的反情况
Node* uncle = parent->left_;
if (uncle && uncle->color_ == RED)
{
parent->color_ = BLACK;
uncle->color_ = BLACK;
Grandfather->color_ = RED;
//如果Grandfather有双亲,则还需要向上更新
cur = Grandfather;
parent = cur->parent_;
}
else
{
if (cur == parent->left_)
{
RotateRight(parent);
swap(cur, parent);
}
parent->color_ = BLACK;
Grandfather->color_ = RED;
RotateLeft(Grandfather);
}
}
}
root->color_ = BLACK;
head->left_ = LeftMost();
head->right_ = RightMost();
return true;
}
//判断红黑树的创建有没有违反性质
bool IsRBTree()
{
Node* root = GetRoot();
//空树
if (nullptr == root)
return true;
//验证性质2
if (BLACK != root->color_)
{
cout << "违反性质2:根节点必须是黑色的。" << endl;
return false;
}
//验证性质3和性质4,先验证性质3
int BlackCount = 0;
Node* cur = root;
while (cur)
{
if (BLACK == cur->color_)
BlackCount++;
cur = cur->left_;
}
//检测其他路径的黑色节点数是否和最左侧路径的相同
int PathCount = 0;
return _IsRBTree(root, BlackCount, PathCount);
}
private:
bool _IsRBTree(Node* root, int BlackCount, int PathCount)
{
if (nullptr == root)
return true;
if (BLACK == root->color_)
PathCount++;
Node* parent = root->parent_;
if (parent != head && RED == parent->color_ && RED == root->color_)
{
cout << "违反性质3:不能有两个连续的红色节点。" << endl;
return false;
}
//当左右子树都为空时,说明走到路径尽头,判断黑色节点数是否相同
if (nullptr == root->left_ && nullptr == root->right_)
{
if (PathCount != BlackCount)
{
cout << "违反性质4:每一条路径上的黑色节点数目相同。" << endl;
return false;
}
}
return _IsRBTree(root->left_, BlackCount, PathCount) &&
_IsRBTree(root->right_, BlackCount, PathCount);
}
void Destory(Node* Proot)
{
if (Proot)
{
Destory(Proot->left_);
Destory(Proot->right_);
delete Proot;
Proot = nullptr;
}
}
//中序遍历
void _InOrder(Node* Proot)
{
if (Proot)
{
_InOrder(Proot->left_);
cout << Proot->val_ << " ";
_InOrder(Proot->right_);
}
}
Node* LeftMost()
{
Node* cur = GetRoot();
if (nullptr == cur)
return head;
while (cur->left_)
cur = cur->left_;
return cur;
}
Node* RightMost()
{
Node* cur = GetRoot();
if (nullptr == cur)
return head;
while (cur->right_)
cur = cur->right_;
return cur;
}
//左单旋
void RotateLeft(Node* parent)
{
Node* subR = parent->right_;
Node* subRL = subR->left_;
parent->right_ = subRL;
subR->left_ = parent;
if (subRL)
subRL->parent_ = parent;
Node* pparent = parent->parent_;
parent->parent_ = subR;
subR->parent_ = pparent;
if (head == pparent)
head->parent_ = subR;
else
{
if (parent == pparent->left_)
pparent->left_ = subR;
else
pparent->right_ = subR;
}
}
//右单旋
void RotateRight(Node* parent)
{
Node* subL = parent->left_;
Node* subLR = subL->right_;
parent->left_ = subLR;
subL->right_ = parent;
if (subLR)
subLR->parent_ = parent;
Node* pparent = parent->parent_;
parent->parent_ = subL;
subL->parent_ = pparent;
if (head == pparent)
head->parent_ = subL;
else
{
if (parent == pparent->left_)
pparent->left_ = subL;
else
pparent->right_ = subL;
}
}
//获取根节点
Node*& GetRoot()
{
return head->parent_;
}
private:
Node* head;
};
void TestRBTree()
{
int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
RBTree<int> t;
for (auto e : a)
{
t.Insert(e);
}
t.InOrder();
if (t.IsRBTree())
cout << "红黑书创建完成!" << endl;
else
cout << "红黑树创建失败!" << endl;
}