1. 红黑树的概念
红黑树的性质1. 每个结点不是红色就是黑色2. 根节点是黑色的3. 如果一个节点是红色的,则它的两个孩子结点是黑色的4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点5. 每个叶子结点都是黑色的 ( 此处的叶子结点指的是空结点 )
2. 红黑树节点的定义
enum Color
{
RED,
BLACK,
};
template <class T>
struct RBTreeNode
{
//构造函数
RBTreeNode(T data)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_data(data)
,_col(RED)
{}
//成员变量
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
T _data;//节点数据
Color _col;//颜色
};
3.红黑树的构造函数
4. 红黑树的插入
如果我们要插入的结点的父亲节点为红色,我们就会出现连续的红色节点,这时我们就需要进行调整了。
uncle为红色节点
当
uncle
节点为红色,此时需要进行变色
由于新插入了红色的cur节点,此时parent与cur出现了连续的红色节点,于是我们将parent改为黑色。但是此时以parent为根的所有路径就会多出一个黑节点,于是把grandfather变为红色,来抵消这个新增的黑节点。但是此时以uncle为根的路径又会少一个黑节点,于是把uncle变黑。
但是我们将grandfather变为了红色,这有可能会影响到上一层节点,比如这样:
我们把grandfather
变红之后,又出现了两个红色节点相连的情况,所以我们要写一个while循环,来反复向上检查。
uncle为空或者黑色节点
单旋
进行单旋,会把c树交给grandfather做子树,而c与uncle为根的路径黑节点数目相同,不违背规则旋转后,parent作新根,grandfather与cur作为左右子树grandfather为根的路径,整体上就会比以cur为根的路径多出一个黑节点(即grandfather本身),因此,将grandfather改为红节点,来平衡parent左右子树的黑节点,而红色节点不能连续出现,再把parent改为黑节点。
//左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* grandparent = parent->_parent;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
subR->_left = parent;
parent->_parent = subR;
if (parent == _root)
{
_root = subR;
}
else
{
if (grandparent->_left == parent)
grandparent->_left = subR;
else
grandparent->_right = subR;
}
subR->_parent = grandparent;
}
//右单旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* grandparent = parent->_parent;
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
subL->_right = parent;
parent->_parent = subL;
if (parent == _root)
{
_root = subL;
}
else
{
if (grandparent->_left == parent)
grandparent->_left = subL;
else
grandparent->_right = subL;
}
subL->_parent = grandparent;
}
双旋
进行双旋,会把C子树交给grandfather做子树,而C与uncle黑节点数目相同,不违背规则;也会把B交给parent做子树,A与B黑节点数目相同,不违背规则;旋转后,cur作新根,grandfather与parent作为左右子树grandfather为根的路径,整体上就会比以parent为根的路径多出一个黑节点(grandfather本身)因此,将grandfather改为红节点,来平衡cur左右子树的黑节点而红色节点不能连续出现,再把cur改为黑节点以上单旋和双旋的变色,看似复杂,其实最后都是把新根的颜色变为黑色,新根的左右子树变为红色。由于我们旋转后,新根都是黑节点,所以不会影响上层,可以直接跳出循环。
//左右双旋
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
RotateL(subL);
RotateR(parent);
}
//右左双旋
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = parent->_left;
RotateR(subR);
RotateL(parent);
}
插入的完整代码
pair<iterator, bool> Insert(const T& data)
{
KeyOfT kot;
//第一次插入
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
//找位置插入
Node* cur = _root, * parent = _root;
while (cur)
{
if (kot(data) < kot(cur->_data))
{
parent = cur;
cur = cur->_left;
}
else if (kot(data) > kot(cur->_data))
{
parent = cur;
cur = cur->_right;
}
else
{
//该数据已经存在
return make_pair(iterator(cur), false);
}
}
//插入数据
cur = new Node(data);
cur->_parent = parent;
if (kot(data) < kot(cur->_data))
parent->_left = cur;
else
parent->_right = cur;
Node* ret = cur;
//检查颜色(当连续出现两个红色时需要调整)
while (parent && parent->_col == RED)
{
Node* grandparent = parent->_parent;
if (parent == grandparent->_left)
{
Node* uncle = grandparent->_right;
//如果uncle存在且为红,则将parent和uncle变黑,grandparent变红
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandparent->_col = RED;
}
//uncle不存在或者为黑
else
{
//将grandparent右旋,grandparent和cur变为红,parent变为黑
if (cur == parent->_left)
{
RotateR(grandparent);
cur->_col = grandparent->_col = RED;
parent->_col = BLACK;
}
//将parent左旋,grandparent右旋,将cur变为黑,parent和grandparent变为红
else
{
RotateL(parent);
RotateR(grandparent);
parent->_col = grandparent->_col = RED;
cur->_col = BLACK;
}
break;
}
}
else
{
Node* uncle = grandparent->_left;
//如果uncle存在且为红,则将parent和uncle变黑,grandparent变红
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandparent->_col = RED;
}
//uncle不存在或者为黑
else
{
//将grandparent左旋,grandparent和cur变为红,parent变为黑
if (cur == parent->_right)
{
RotateL(grandparent);
cur->_col = grandparent->_col = RED;
parent->_col = BLACK;
}
//将parent右旋,grandparent左旋,将cur变为黑,parent和grandparent变为红
else
{
RotateR(parent);
RotateL(grandparent);
parent->_col = grandparent->_col = RED;
cur->_col = BLACK;
}
break;
}
}
}
//把根节点变为黑
_root->_col = BLACK;
return make_pair(iterator(ret), true);
}
5. 红黑树的迭代器
operator++
当迭代器指向哪一个节点,说明当前就遍历到了哪一个节点,此时迭代器处于这个蓝色框中的节点,说明这个节点的左子树已经遍历完了,刚好遍历到这个蓝色框节点。因此下一步就是中序遍历右子树,即让迭代器走到当前节点的右子树位置,并且找到右子树的最左节点,该节点就是下一个节点。
如果右子树为空,说明整颗子树都遍历完毕了,那么我们就要向上移动,走到当前节点的父节点处:
但是对于这个父节点而言,其左子树遍历完了,刚刚右子树遍历完毕后,走到了当前节点,说明当前节点也遍历完毕了,此时还要向上移动,以此类推,直到走到第一个当前节点是父节点的左子树的情况。
1.如果迭代器当前节点的右子树不为空,遍历右子树(找到右子树的最左节点)
2.如果迭代器当前节点的右子树为空,向上找前一个节点是当前节点的左子树的节点
operator--
同理,只是相反的:
1.如果迭代器当前节点的左子树不为空,遍历左子树(找到左子树的最右节点)
2.如果迭代器当前节点的左子树为空,向上找前一个节点是当前节点的右子树的节点
迭代器的完整代码
//实现迭代器
template<class T, class Ref, class Ptr>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, Ref, Ptr> Self;
Node* _node;
//构造函数
RBTreeIterator(const Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &(_node->_data);
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
bool operator!=(const Self& s)const
{
return _node != s._node;
}
//前置++
Self& operator++()
{
//如果右子树不为空,说明该树未取完,要取右子树的最左结点
if (_node->_right)
{
Node* left = _node->_right;
while (left->_left)
{
left = left->_left;
}
_node = left;
}
//右子树为空,说明该树已经取完,要回到cur为左孩子的parent
else
{
Node* cur = _node, * parent = cur->_parent;
while (parent && parent->_right == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
//后置++
Self operator++(int)
{
Self old = new Self(_node);
//如果右子树不为空,说明该树未取完,要取右子树的最左结点
if (_node->_right)
{
Node* left = _node->_right;
while (left->_left)
{
left = left->_left;
}
_node = left;
}
//右子树为空,说明该树已经取完,要回到cur为左孩子的parent
else
{
Node* cur = _node, * parent = cur->_parent;
while (parent && parent->_right == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return old;
}
//前置--
Self& operator--()
{
//如果左子树不为空,说明该树未取完,要取左子树的最右结点
if (_node->_left)
{
Node* right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right;
}
//左子树为空,说明该树已经取完,要回到cur为右孩子的parent
else
{
Node* cur = _node, * parent = cur->_parent;
while (parent && parent->_left == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
//后置--
Self operator--(int)
{
Self old = new Self(_node);
//如果左子树不为空,说明该树未取完,要取左子树的最右结点
if (_node->_left)
{
Node* right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right;
}
//左子树为空,说明该树已经取完,要回到cur为右孩子的parent
else
{
Node* cur = _node, * parent = cur->_parent;
while (parent && parent->_left == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return old;
}
};
6.红黑树的判定h
bool _IsRBTree(Node* root, int count, int blacknum)
{
if (root == nullptr)
{
if (count != blacknum)
{
return false;
}
return true;
}
if (root->_col == BLACK)
count++;
return _IsRBTree(root->_left, count, blacknum) &&
_IsRBTree(root->_right, count, blacknum);
}
bool IsRBTree()
{
if (_root->_col == RED)
{
return false;
}
int blacknum = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
blacknum++;
cur = cur->_left;
}
return _IsRBTree(_root, 0, blacknum);
}
7.红黑树的完整代码
#include <iostream>
#include <vector>
using namespace std;
namespace lbk
{
enum Color
{
RED,
BLACK,
};
template <class T>
struct RBTreeNode
{
//构造函数
RBTreeNode(T data)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_data(data)
,_col(RED)
{}
//成员变量
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
T _data;//节点数据
Color _col;//颜色
};
//实现迭代器
template<class T,class Ref,class Ptr>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, Ref, Ptr> Self;
Node* _node;
//构造函数
RBTreeIterator(const Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &(_node->_data);
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
bool operator!=(const Self& s)const
{
return _node != s._node;
}
//前置++
Self& operator++()
{
//如果右子树不为空,说明该树未取完,要取右子树的最左结点
if (_node->_right)
{
Node* left = _node->_right;
while (left->_left)
{
left = left->_left;
}
_node = left;
}
//右子树为空,说明该树已经取完,要回到cur为左孩子的parent
else
{
Node* cur=_node,*parent = cur->_parent;
while (parent && parent->_right==cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
//后置++
Self operator++(int)
{
Self old = new Self(_node);
//如果右子树不为空,说明该树未取完,要取右子树的最左结点
if (_node->_right)
{
Node* left = _node->_right;
while (left->_left)
{
left = left->_left;
}
_node = left;
}
//右子树为空,说明该树已经取完,要回到cur为左孩子的parent
else
{
Node* cur = _node, * parent = cur->_parent;
while (parent && parent->_right == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return old;
}
//前置--
Self& operator--()
{
Self old = new Self(_node);
//如果左子树不为空,说明该树未取完,要取左子树的最右结点
if (_node->_left)
{
Node* right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right;
}
//左子树为空,说明该树已经取完,要回到cur为右孩子的parent
else
{
Node* cur = _node, * parent = cur->_parent;
while (parent && parent->_left == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
//后置--
Self operator--(int)
{
//如果左子树不为空,说明该树未取完,要取左子树的最右结点
if (_node->_left)
{
Node* right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right;
}
//左子树为空,说明该树已经取完,要回到cur为右孩子的parent
else
{
Node* cur = _node, * parent = cur->_parent;
while (parent && parent->_left == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
};
template<class K,class T,class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, T&, T*> iterator;
public:
//构造函数
RBTree()
:_root(nullptr)
{}
//析构函数
void Destroy(Node* root)
{
if (root == nullptr)
{
return;
}
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
~RBTree()
{
Destroy(_root);
_root = nullptr;
}
iterator begin()
{
Node* left = _root;
while (left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
pair<iterator,bool> Insert(const T& data)
{
KeyOfT kot;
//第一次插入
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
//找位置插入
Node* cur = _root, * parent = _root;
while (cur)
{
if (kot(data)< kot(cur->_data))
{
parent = cur;
cur = cur->_left;
}
else if (kot(data) > kot(cur->_data))
{
parent = cur;
cur = cur->_right;
}
else
{
//该数据已经存在
return make_pair(iterator(cur), false);
}
}
//插入数据
cur = new Node(data);
cur->_parent = parent;
if (kot(data) < kot(cur->_data))
parent->_left = cur;
else
parent->_right = cur;
Node* ret = cur;
//检查颜色(当连续出现两个红色时需要调整)
while (parent&&parent->_col==RED)
{
Node* grandparent = parent->_parent;
if (parent == grandparent->_left)
{
Node* uncle = grandparent->_right;
//如果uncle存在且为红,则将parent和uncle变黑,grandparent变红
if (uncle && uncle->_col == RED)
{
parent->_col=uncle->_col = BLACK;
grandparent->_col = RED;
}
//uncle不存在或者为黑
else
{
//将grandparent右旋,grandparent和cur变为红,parent变为黑
if (cur == parent->_left)
{
RotateR(grandparent);
cur->_col=grandparent->_col = RED;
parent->_col = BLACK;
}
//将parent左旋,grandparent右旋,将cur变为黑,parent和grandparent变为红
else
{
RotateL(parent);
RotateR(grandparent);
parent->_col = grandparent->_col = RED;
cur->_col = BLACK;
}
break;
}
}
else
{
Node* uncle = grandparent->_left;
//如果uncle存在且为红,则将parent和uncle变黑,grandparent变红
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandparent->_col = RED;
}
//uncle不存在或者为黑
else
{
//将grandparent左旋,grandparent和cur变为红,parent变为黑
if (cur == parent->_right)
{
RotateL(grandparent);
cur->_col = grandparent->_col = RED;
parent->_col = BLACK;
}
//将parent右旋,grandparent左旋,将cur变为黑,parent和grandparent变为红
else
{
RotateR(parent);
RotateL(grandparent);
parent->_col = grandparent->_col = RED;
cur->_col = BLACK;
}
break;
}
}
}
//把根节点变为黑
_root->_col = BLACK;
return make_pair(iterator(ret), true);
}
bool _IsRBTree(Node* root,int count,int blacknum)
{
if (root == nullptr)
{
if (count != blacknum)
{
return false;
}
return true;
}
if (root->_col == BLACK)
count++;
return _IsRBTree(root->_left, count, blacknum) &&
_IsRBTree(root->_right, count, blacknum);
}
bool IsRBTree()
{
if (_root->_col == RED)
{
return false;
}
int blacknum = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
blacknum++;
cur = cur->_left;
}
return _IsRBTree(_root, 0, blacknum);
}
void _InOrder(Node* root)
{
KeyOfT okt;
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << kof(root->_data) << " ";
_InOrder(root->_right);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
private:
//左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* grandparent = parent->_parent;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
subR->_left = parent;
parent->_parent = subR;
if (parent == _root)
{
_root = subR;
}
else
{
if (grandparent->_left == parent)
grandparent->_left = subR;
else
grandparent->_right = subR;
}
subR->_parent = grandparent;
}
//右单旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* grandparent = parent->_parent;
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
subL->_right = parent;
parent->_parent = subL;
if (parent == _root)
{
_root = subL;
}
else
{
if (grandparent->_left == parent)
grandparent->_left = subL;
else
grandparent->_right = subL;
}
subL->_parent = grandparent;
}
//左右双旋
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
RotateL(subL);
RotateR(parent);
}
//右左双旋
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = parent->_left;
RotateR(subR);
RotateL(parent);
}
Node* _root;
};
}