map和set其底层都是按照二叉搜索树来实现的,但是二叉搜索树有其自身的缺陷,假如往树中插入的元素有序或者接近有序,二叉搜索树就会退化成单支树,时间复杂度会退化成O(N),因此map、set等关联式容器的底层结构是对二叉树进行了平衡处理,即采用平衡树来实现。
二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
template<class K, class V>
struct AVLTreeNode
{
pair<K, V> _val;
AVLTreeNode<K, V>* _pLeft;
AVLTreeNode<K, V>* _pRight;
AVLTreeNode<K, V>* _pParent;
int _bf;
AVLTreeNode(const pair<K,V>& val)
:_val(val)
, _pLeft(nullptr)//该节点的左孩子
, _pRight(nullptr)//该节点的右孩子
, _pParent(nullptr)//该节点的父节点
, _bf(0)//该节点的平衡因子
{}
};
AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么AVL树的插入过程可以分为两步:
bool Insert(const pair<K, V> kv)
{
// 1. 先按照二叉搜索树的规则将节点插入到AVL树中
// ...
// 2. 新节点插入后,AVL树的平衡性可能会遭到破坏,此时就需要更新平衡因子,并检测是否破坏了AVL树的平衡性
/*
pCur插入后,pParent的平衡因子一定需要调整,在插入之前,pParent的平衡因子分为三种情况:-1,0, 1, 分以下两种情况:
1. 如果pCur插入到pParent的左侧,只需给pParent的平衡因子-1即可
2. 如果pCur插入到pParent的右侧,只需给pParent的平衡因子+1即可
此时:pParent的平衡因子可能有三种情况:0,正负1, 正负2
1. 如果pParent的平衡因子为0,说明插入之前pParent的平衡因子为正负1,插入后被调整成0,此时满足AVL树的性质,插入成功
2. 如果pParent的平衡因子为正负1,说明插入前pParent的平衡因子一定为0,插入后被更新成正负1,此时以pParent为根的树的高度增加,需要继续向上更新
3. 如果pParent的平衡因子为正负2,则pParent的平衡因子违反平衡树的性质,需要对其进行旋转处理
*/
if (_root == nullptr)
{
_root = new Node(kv);
_root->_bf = 0;
return true;
}
Node* Parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_val.first > kv.first)
{
Parent = cur;
cur = cur->_pLeft;
}
else if (cur->_val.first < kv.first)
{
Parent = cur;
cur = cur->_pRight;
}
else
{
return false;
}
}
cur = new Node(kv);
if (Parent->_val > cur->_val)
{
Parent->_pLeft = cur;
cur->_pParent = Parent;
}
else
{
Parent->_pRight = cur;
cur->_pParent = Parent;
}
while (Parent)
{
if (cur == Parent->_pLeft)
Parent->_bf--;
else
{
Parent->_bf++;
}
if (Parent->_bf == 0)
break;
else if (abs(Parent->_bf) == 1)
{
cur = Parent;
Parent = Parent->_pParent;
}
else if (abs(Parent->_bf) == 2)
{
if (Parent->_bf == 2){
if (cur->_bf == 1){
RotateL(Parent);
}
else if (cur->_bf == -1){
RotateRL(Parent);
}
}
else if (Parent->_bf == -2){
if (cur->_bf == -1){
RotateR(Parent);
}
else if (cur->_bf == 1){
RotateLR(Parent);
}
}
break;
}
else
{
assert(false);
}
}
return true;
}
如果在一棵原本是平衡的AVL树中插入一个新节点,可能造成不平衡,此时必须调整树的结构,使之平衡化。根据节点插入位置的不同,AVL树的旋转分为四种:
/*
上图在插入前,AVL树是平衡的,新节点插入到30的左子树(注意:此处不是左孩子)中,30左子树增
加
了一层,导致以60为根的二叉树不平衡,要让60平衡,只能将60左子树的高度减少一层,右子树增加
一层,
即将左子树往上提,这样60转下来,因为60比30大,只能将其放在30的右子树,而如果30有右子
树,右子树根的值一定大于30,小于60,只能将其放在60的左子树,旋转完成后,更新节点的平衡因子
即可。在旋转过程中,有以下几种情况需要考虑:
1. 30节点的右孩子可能存在,也可能不存在
2. 60可能是根节点,也可能是子树
如果是根节点,旋转完成后,要更新根节点
如果是子树,可能是某个节点的左子树,也可能是右子树
同学们再此处可举一些详细的例子进行画图,考虑各种情况,加深旋转的理解
*/
void _RotateR(PNode pParent)
{
// pSubL: pParent的左孩子
// pSubLR: pParent左孩子的右孩子,注意:该
PNode pSubL = pParent->_pLeft;
PNode pSubLR = pSubL->_pRight;
// 旋转完成之后,30的右孩子作为双亲的左孩子
pParent->_pLeft = pSubLR;
// 如果30的左孩子的右孩子存在,更新亲双亲
if(pSubLR)
pSubLR->_pParent = pParent;
// 60 作为 30的右孩子
pSubL->_pRight = pParent;
// 因为60可能是棵子树,因此在更新其双亲前必须先保存60的双亲
PNode pPParent = pParent->_pParent;
// 更新60的双亲
pParent->_pParent = pSubL;
// 更新30的双亲
pSubL->_pParent = pPParent;
// 如果60是根节点,根新指向根节点的指针
if(NULL == pPParent)
{
_pRoot = pSubL;
pSubL->_pParent = NULL;
}
else
{
// 如果60是子树,可能是其双亲的左子树,也可能是右子树
if(pPParent->_pLeft == pParent)
pPParent->_pLeft = pSubL;
else
pPParent->_pRight = pSubL;
}
// 根据调整后的结构更新部分节点的平衡因子
pParent->_bf = pSubL->_bf = 0;
}
//左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_pRight;
Node* subRL = subR->_pLeft;
parent->_pRight = subRL;
if (subRL)
subRL->_pParent = parent;
subR->_pLeft = parent;
Node* ppNode = parent->_pParent;
parent->_pParent = subR;
if (parent == _root)
{
_root = subR;
_root->_pParent = nullptr;
}
else
{
if (ppNode->_pLeft == subR)
ppNode->_pLeft = subR;
else
{
ppNode->_pRight = subR;
}
subR->_pParent = ppNode;
}
parent->_bf = subR->_bf = 0;
}
将双旋变成单旋后再旋转,即:先对30进行左单旋,然后再对90进行右单旋,旋转完成后再考虑平衡因子的更新。
// 旋转之前,60的平衡因子可能是-1/0/1,旋转完成之后,根据情况对其他节点的平衡因子进行调整
void _RotateLR(PNode pParent)
{
PNode pSubL = pParent->_pLeft;
PNode pSubLR = pSubL->_pRight;
// 旋转之前,保存pSubLR的平衡因子,旋转完成之后,需要根据该平衡因子来调整其他节点的平
衡因子
int bf = pSubLR->_bf;
// 先对30进行左单旋
_RotateL(pParent->_pLeft);
// 再对90进行右单旋
_RotateR(pParent);
if(1 == bf)
pSubL->_bf = -1;
else if(-1 == bf)
pParent->_bf = 1;
}
void RotateRL(Node* parent)
{
Node* subR = parent->_pRight;
Node* subRL = subR->_pLeft;
int bf = subRL->_bf; //保存subRL的平衡因子,因为在下面两行会置 0
RotateR(parent->_pRight);
RotateL(parent);
if (bf == 0){
parent->_bf = subRL->_bf = subR->_bf = 0;
}
else if (bf == 1){ //在c插入的新结点
subR->_bf = 0;
parent->_bf = -1;
subRL->_bf = 0;
}
else if (bf == -1){ //在b插入的新结点
parent->_bf = 0;
subR->_bf = 1;
subRL->_bf = 0;
}
}
总结:
假如以pParent为根的子树不平衡,即pParent的平衡因子为2或者-2,分以下情况考虑
旋转完成后,原pParent为根的子树个高度降低,已经平衡,不需要再向上更新。
AVL树是在二叉搜索树的基础上加入了平衡性的限制,因此要验证AVL树,可以分两步:
int _Height(PNode pRoot);
bool _IsBalanceTree(PNode pRoot)
{
// 空树也是AVL树
if (nullptr == pRoot) return true;
// 计算pRoot节点的平衡因子:即pRoot左右子树的高度差
int leftHeight = _Height(pRoot->_pLeft);
int rightHeight = _Height(pRoot->_pRight);
int diff = rightHeight - leftHeight;
// 如果计算出的平衡因子与pRoot的平衡因子不相等,或者
// pRoot平衡因子的绝对值超过1,则一定不是AVL树
if (diff != pRoot->_bf || (diff > 1 || diff < -1))
return false;
// pRoot的左和右如果都是AVL树,则该树一定是AVL树
return _IsBalanceTree(pRoot->_pLeft) && _IsBalanceTree(pRoot->_pRight);
}
因为AVL树也是二叉搜索树,可按照二叉搜索树的方式将节点删除,然后再更新平衡因子,只不错与删除不同的时,删除节点后的平衡因子更新,最差情况下一直要调整到根节点的位置。
AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度,即 。但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:
因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。
// 节点的颜色
enum Color{RED, BLACK};
// 红黑树节点的定义
template<class ValueType>
struct RBTreeNode
{
RBTreeNode(const ValueType& data = ValueType(),Color color = RED)
: _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr)
, _data(data), _color(color)
{}
RBTreeNode<ValueType>* _pLeft; // 节点的左孩子
RBTreeNode<ValueType>* _pRight; // 节点的右孩子
RBTreeNode<ValueType>* _pParent; // 节点的双亲(红黑树需要旋转,为了实现简单给出该字段)
ValueType _data; // 节点的值域
Color _color; // 节点的颜色
};
为了后续实现关联式容器简单,红黑树的实现中增加一个头结点,因为跟节点必须为黑色,为了与根节点进行区分,将头结点给成黑色,并且让头结点的 pParent 域指向红黑树的根节点,pLeft域指向红黑树中最小的节点,_pRight域指向红黑树中最大的节点,如下:
红黑树是在二叉搜索树的基础上加上其平衡限制条件,因此红黑树的插入可分为两步:
template<class ValueType>
class RBTree{
typedef RBTreeNode Node;
public:
bool Insert(const ValueType& data)
{
……
PNode& pRoot = GetRoot();
if (nullptr == pRoot)
{
pRoot = new Node(data, BLACK);
// 根的双亲为头节点
pRoot->_pParent = _pHead;
_pHead->_pParent = pRoot;
}
else
{
// 1. 按照二叉搜索的树方式插入新节点
// 2. 检测新节点插入后,红黑树的性质是否造到破坏,
// 若满足直接退出,否则对红黑树进行旋转着色处理
}
// 根节点的颜色可能被修改,将其改回黑色
pRoot->_color = BLACK;
_pHead->_pLeft = LeftMost();
_pHead->_pRight = RightMost();
return true;
}
private:
PNode& GetRoot(){ return _pHead->_pParent; }
// 获取红黑树中最小节点,即最左侧节点
PNode LeftMost();
// 获取红黑树中最大节点,即最右侧节点
PNode RightMost();
private:
Node* _root;
};
因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连在一起的红色节点,此时需要对红黑树分情况来讨论:
pair<iterator, bool> Insert(const T& val){
//插入节点
if (_root == nullptr)
{
_root = new Node(val);
_root->_color = BLACK;
return make_pair(iterator(_root), true);
}
//寻找位置
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_data < val){
parent = cur;
cur = cur->_pRight;
}
else if (cur->_data > val){
parent = cur;
cur = cur->_pLeft;
}
else{
return make_pair(iterator(cur), false);
}
}
cur = new Node(val);
Node* newnode = cur;
cur->_color = RED;
//插入适当位置
if (parent->_data < val){
parent->_pRight = cur;
cur->_pParent = parent;
}
else{
parent->_pLeft = cur;
cur->_pParent = parent;
}
//变色处理
//父节点为红色节点
while (parent && parent->_color == RED){
Node* grandfather = parent->_pParent;
//父亲是祖父节点左孩子
if (parent == grandfather->_pLeft){
Node* uncle = grandfather->_pRight;
// 1.叔叔节点存在且为红
if (uncle && uncle->_color == RED){
parent->_color = BLACK;
uncle->_color = BLACK;
grandfather->_color = RED;
cur = grandfather;
parent = cur->_pParent;
}
//叔叔节点不存在或者叔叔节点为黑
else{
if (cur == parent->_pRight){
RotateL(parent);
swap(parent, cur);
}
RotateR(grandfather);
parent->_color = BLACK;
grandfather->_color = RED;
break;
}
}
//父亲节点是祖父节点右孩子
else{
Node* uncle = grandfather->_pLeft;
if (uncle && uncle->_color == RED){
parent->_color = BLACK;
uncle->_color = BLACK;
grandfather->_color = RED;
cur = grandfather;
parent = cur->_pParent;
}
else{
if (cur == parent->_pLeft){
RotateR(parent);
swap(parent, cur);
}
RotateL(grandfather);
parent->_color = BLACK;
grandfather->_color = RED;
break;
}
}
}
_root->_color = BLACK;
return make_pair(iterator(newnode), true);
}
void RotateL(Node* parent){
Node* subR = parent->_pRight;
Node* subRL = subR->_pLeft;
parent->_pRight = subRL;
if (subRL)
subRL->_pParent = parent;
subR->_pLeft = parent;
Node* pNode = parent->_pParent;
parent->_pParent = subR;
if (parent == _root){
_root = subR;
_root->_pParent = nullptr;
}
else{
if (pNode->_pLeft == parent)
pNode->_pLeft = subR;
else
pNode->_pRight = subR;
subR->_pParent = pNode;
}
}
void RotateR(Node* parent){
Node* subL = parent->_pLeft;
Node* subLR = subL->_pRight;
parent->_pLeft = subLR;
if (subLR)
subLR->_pParent = parent;
subL->_pRight = parent;
Node* pNode = parent->_pParent;
parent->_pParent = subL;
if (pNode == nullptr){
_root = subL;
_root->_pParent = nullptr;
}
else{
if (pNode->_pLeft == parent){
pNode->_pLeft = subL;
}
else{
pNode->_pRight = subL;
}
subL->_pParent = pNode;
}
}
红黑树的检测分为两步:
bool IsValidRBTree(){
Node* pRoot = _root;
// 空树也是红黑树
if (nullptr == pRoot)
return true;
// 检测根节点是否满足情况
if (BLACK != pRoot->_color){
cout << "违反红黑树性质二:根节点必须为黑色" << endl;
return false;
}
// 获取任意一条路径中黑色节点的个数
size_t blackCount = 0;
Node* pCur = pRoot;
while (pCur){
if (BLACK == pCur->_color)
blackCount++;
pCur = pCur->_pLeft;
}
// 检测是否满足红黑树的性质,k用来记录路径中黑色节点的个数
size_t k = 0;
return _IsValidRBTree(pRoot, k, blackCount);
}
bool _IsValidRBTree(Node* pRoot, size_t k, const size_t blackCount){
//走到null之后,判断k和black是否相等
if (nullptr == pRoot){
if (k != blackCount){
cout << "违反性质四:每条路径中黑色节点的个数必须相同" << endl;
return false;
}
return true;
}
// 统计黑色节点的个数
if (BLACK == pRoot->_color)
k++;
// 检测当前节点与其双亲是否都为红色
Node* pParent = pRoot->_pParent;
if (pParent && RED == pParent->_color && RED == pRoot->_color){
cout << "违反性质三:没有连在一起的红色节点" << endl;
return false;
}
return _IsValidRBTree(pRoot->_pLeft, k, blackCount) &&
_IsValidRBTree(pRoot->_pRight, k, blackCount);
}
红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O(log N),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。
迭代器的好处是可以方便遍历,是数据结构的底层实现与用户透明。如果想要给红黑树增加迭代器,需要考虑以前问题:
// 找迭代器的下一个节点,下一个节点肯定比其大
void Increasement()
{
//分两种情况讨论:_pNode的右子树存在和不存在
// 右子树存在
if(_pNode->_pRight)
{
// 右子树中最小的节点,即右子树中最左侧节点
_pNode = _pNode->_pRight;
while(_pNode->_pLeft)
_pNode = _pNode->_pLeft;
}
else
{
// 右子树不存在,向上查找,直到_pNode != pParent->right
PNode pParent = _pNode->_pParent;
while(pParent->_pRight == _pNode)
{
_pNode = pParent;
pParent = _pNode->_pParent;
}
// 特殊情况:根节点没有右子树
if(_pNode->_pRight != pParent)
_pNode = pParent;
}
}
// 获取迭代器指向节点的前一个节点
void Decreasement()
{
//分三种情况讨论:_pNode 在head的位置,_pNode 左子树存在,_pNode 左子树不存在
// 1. _pNode 在head的位置,--应该将_pNode放在红黑树中最大节点的位置
if(_pNode->_pParent->_pParent == _pNode && _pNode->_color == RED)
_pNode = _pNode->_pRight;
else if(_pNode->_pLeft)
{
// 2. _pNode的左子树存在,在左子树中找最大的节点,即左子树中最右侧节点
_pNode = _pNode->_pLeft;
while(_pNode->_pRight)
_pNode = _pNode->_pRight;
}
else
{
// _pNode的左子树不存在,只能向上找
PNode pParent = _pNode->_pParent;
while(_pNode == pParent->_pLeft)
{
_pNode = pParent;
pParent = _pNode->_pParent;
}
_pNode = pParent;
}
}
#include
using namespace std;
enum Color{
RED,
BLACK
};
template<class ValueType>
struct RBTreeNode
{
RBTreeNode<ValueType>* _pLeft;
RBTreeNode<ValueType>* _pRight;
RBTreeNode<ValueType>* _pParent;
ValueType _data;
Color _color;
RBTreeNode(const ValueType& data = ValueType(),Color color = RED)
:_pLeft(nullptr)
, _pRight(nullptr)
, _pParent(nullptr)
, _data(data)
, _color(color)
{}
};
template<class T,class Ptr,class Ref>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, Ptr, Ref> Self;
Node* _node;
RBTreeIterator(Node* node)
:_node(node)
{}
Ref operator*(){
return _node->_data;
}
Ref operator->(){
return &_node->_data;
}
Self& operator++()
{
if (_node->_pRight != nullptr)
{
_node = _node->_pRight;
while (_node->_pLeft != nullptr)
{
_node = _node->_pLeft;
}
}
else
{
Node* parent = _node->_pParent;
while (parent != nullptr && _node == parent->_pRight){
_node = parent;
parent = _node->_parent;
}
_node = parent;
}
return *this;
}
Self operator++(int){
Self tmp(*this);
++(*this);
return tmp;
}
Self& operator--(){
if (_node->_pLeft != nullptr)
{
_node = _node->_pLeft;
while (_node->_pLeft != nullptr)
{
_node = _node->_pRight;
}
}
else
{
Node* parent = _node->_pParent;
while (parent != nullptr && _node == parent->_pLeft){
_node = parent;
parent = _node->_parent;
}
_node = parent;
}
return *this;
}
Self operator--(int){
Self tmp(*this);
--(*this);
return tmp;
}
bool operator != (const Self& s) const{
return _node != s._node;
}
bool operator == (const Self& s) const{
return _node == s._node;
}
};
template<class K, class T>
class RBTree{
typedef RBTreeNode<T> Node;
public:
typedef RBTreeIterator<T, T*, T&> iterator;
typedef RBTreeIterator<T, const T*, const T&> const_iterator;
RBTree() = default;
// 拷贝构造 + operator=
// 析构函数
iterator begin(){
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return iterator(cur);
}
iterator end(){
return iterator(nullptr);
}
const_iterator begin() const{
Node* cur = _root;
while (cur && cur->_left){
cur = cur->_left;
}
return const_iterator(cur);
}
const_iterator end() const{
return const_iterator(nullptr);
}
pair<iterator, bool> Insert(const T& val){
//插入节点
if (_root == nullptr)
{
_root = new Node(val);
_root->_color = BLACK;
return make_pair(iterator(_root), true);
}
//寻找位置
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_data < val){
parent = cur;
cur = cur->_pRight;
}
else if (cur->_data > val){
parent = cur;
cur = cur->_pLeft;
}
else{
return make_pair(iterator(cur), false);
}
}
cur = new Node(val);
Node* newnode = cur;
cur->_color = RED;
//插入适当位置
if (parent->_data < val){
parent->_pRight = cur;
cur->_pParent = parent;
}
else{
parent->_pLeft = cur;
cur->_pParent = parent;
}
//变色处理
//父节点为红色节点
while (parent && parent->_color == RED){
Node* grandfather = parent->_pParent;
//父亲是祖父节点左孩子
if (parent == grandfather->_pLeft){
Node* uncle = grandfather->_pRight;
// 1.叔叔节点存在且为红
if (uncle && uncle->_color == RED){
parent->_color = BLACK;
uncle->_color = BLACK;
grandfather->_color = RED;
cur = grandfather;
parent = cur->_pParent;
}
//叔叔节点不存在或者叔叔节点为黑
else{
if (cur == parent->_pRight){
RotateL(parent);
swap(parent, cur);
}
RotateR(grandfather);
parent->_color = BLACK;
grandfather->_color = RED;
break;
}
}
//父亲节点是祖父节点右孩子
else{
Node* uncle = grandfather->_pLeft;
if (uncle && uncle->_color == RED){
parent->_color = BLACK;
uncle->_color = BLACK;
grandfather->_color = RED;
cur = grandfather;
parent = cur->_pParent;
}
else{
if (cur == parent->_pLeft){
RotateR(parent);
swap(parent, cur);
}
RotateL(grandfather);
parent->_color = BLACK;
grandfather->_color = RED;
break;
}
}
}
_root->_color = BLACK;
return make_pair(iterator(newnode), true);
}
void RotateL(Node* parent){
Node* subR = parent->_pRight;
Node* subRL = subR->_pLeft;
parent->_pRight = subRL;
if (subRL)
subRL->_pParent = parent;
subR->_pLeft = parent;
Node* pNode = parent->_pParent;
parent->_pParent = subR;
if (parent == _root){
_root = subR;
_root->_pParent = nullptr;
}
else{
if (pNode->_pLeft == parent)
pNode->_pLeft = subR;
else
pNode->_pRight = subR;
subR->_pParent = pNode;
}
}
void RotateR(Node* parent){
Node* subL = parent->_pLeft;
Node* subLR = subL->_pRight;
parent->_pLeft = subLR;
if (subLR)
subLR->_pParent = parent;
subL->_pRight = parent;
Node* pNode = parent->_pParent;
parent->_pParent = subL;
if (pNode == nullptr){
_root = subL;
_root->_pParent = nullptr;
}
else{
if (pNode->_pLeft == parent){
pNode->_pLeft = subL;
}
else{
pNode->_pRight = subL;
}
subL->_pParent = pNode;
}
}
iterator Find(const K& k){
Node* cur = _root;
while (cur){
KeyOfValue kov;
if (kov(cur->_data) < k){
cur = cur->_pRight;
}
else if (kov(cur->_data) > k){
cur = cur->_pLeft;
}
else{
return iterator(cur);
}
}
return end();
}
bool IsValidRBTree(){
Node* pRoot = _root;
// 空树也是红黑树
if (nullptr == pRoot)
return true;
// 检测根节点是否满足情况
if (BLACK != pRoot->_color){
cout << "违反红黑树性质二:根节点必须为黑色" << endl;
return false;
}
// 获取任意一条路径中黑色节点的个数
size_t blackCount = 0;
Node* pCur = pRoot;
while (pCur){
if (BLACK == pCur->_color)
blackCount++;
pCur = pCur->_pLeft;
}
// 检测是否满足红黑树的性质,k用来记录路径中黑色节点的个数
size_t k = 0;
return _IsValidRBTree(pRoot, k, blackCount);
}
bool _IsValidRBTree(Node* pRoot, size_t k, const size_t blackCount){
//走到null之后,判断k和black是否相等
if (nullptr == pRoot){
if (k != blackCount){
cout << "违反性质四:每条路径中黑色节点的个数必须相同" << endl;
return false;
}
return true;
}
// 统计黑色节点的个数
if (BLACK == pRoot->_color)
k++;
// 检测当前节点与其双亲是否都为红色
Node* pParent = pRoot->_pParent;
if (pParent && RED == pParent->_color && RED == pRoot->_color){
cout << "违反性质三:没有连在一起的红色节点" << endl;
return false;
}
return _IsValidRBTree(pRoot->_pLeft, k, blackCount) &&
_IsValidRBTree(pRoot->_pRight, k, blackCount);
}
void InOrder(){
_InOrder(_root);
cout << endl;
}
void _InOrder(Node* root){
if (root == nullptr)
return;
_InOrder(root->_pLeft);
cout << root->_data << " ";
_InOrder(root->_pRight);
}
private:
Node* _root = nullptr;
};
void TestRBtree(){
RBTree<int, int> t;
int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
//int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14, };
for (auto e : a){
t.Insert(e);
}
t.InOrder();
cout << t.IsValidRBTree() << endl;
}
#include"RBTree.h"
namespace fxl
{
template<class K, class V>
class map
{
typedef pair<K, V> ValueType;
// 作用:将value中的key提取出来
struct KeyOfValue
{
const K& operator()(const ValueType& v)
{
return v.first;
}
};
typedef RBTree<K, ValueType, KeyOfValue> RBTree;
public:
typedef typename RBTree::Iterator iterator;
public:
map(){}
iterator begin(){ return _t.Begin(); }
iterator end(){ return _t.End(); }
size_t size()const{ return _t.Size(); }
bool empty()const{ return _t.Empty(); }
V& operator[](const K& key)
{
return (*(_t.Insert(ValueType(key, V()))).first).second;
}
const V& operator[](const K& key)const;
pair<iterator, bool> insert(const ValueType& data) { return _t.Insert(data); }
void clear(){ _t.Clear(); }
iterator find(const K& key){ return _t.Find(key); }
private:
RBTree _t;
};
}
#include"RBTree.h"
namespace fxl
{
template<class K>
class set
{
typedef K ValueType;
struct KeyOfValue
{
const K& operator()(const ValueType& key)
{
return key;
}
};
// 红黑树类型重命名
typedef RBTree<K, ValueType, KeyOfValue> RBTree;
public:
typedef typename RBTree::Iterator iterator;
public:
Set(){}
iterator begin(){ return _t.Begin(); }
iterator end(){ return _t.End(); }
size_t size()const{ return _t.Size(); }
bool empty()const{ return _t.Empty(); }
pair<iterator, bool> insert(const ValueType& data)
{
return _t.Insert(data);
}
void clear(){ _t.Clear(); }
iterator find(const K& key){ return _t.Find(key); }
private:
RBTree _t;
};
}