目录
一,红黑树的介绍
红黑树的概念
红黑树的性质
红黑树节点的定义
红黑树的结构
二,红黑树的插入
三,红黑树的验证及删除
红黑树的验证
红黑树的删除
红黑树与AVL树的比较
四,红黑树的应用
红黑树的应用
红黑树模拟实现set/map
一,红黑树的介绍
enum Color { RED, BLACK };
template
struct RBTreeNode
{
RBTreeNode(const ValueType& data = ValueType(), Color color=RED)
:_pLeft(nullptr)
,_pRight(nullptr)
,_pParent(nullptr)
,_data(data)
,_color(color)
{}
RBTreeNode* _pLeft;
RBTreeNode* _pRight;
RBTreeNode* _pParent;
ValueType _data;
Color _color;
};
为了后续实现关联式容器简单,红黑树的实现中增加一个头节点;因为根节点必须为黑色,为了与根节点进行区分,将头节点给成黑色,并让头节点的_pParent指向红黑树的根节点,_pLeft指向指向红黑树中最小的节点,_pRight指向红黑树中最大的节点;
二,红黑树的插入
红黑树是在二叉搜索树的基础上加上其平衡限制条件,红黑树的插入可分为两步:
1,按照二叉搜索树的规则插入新节点;
template
class RBTree
{
bool Insert(const ValueType& data)
{
pNode& pRoot = GetRoot();
if (pRoot == nullptr)
{
pRoot = new Node(data, BLACK);
pRoot->_pParent = _pHead;
_pHead->_pParent = pRoot;
}
else
{
pRoot->_color = BLACK;
_pHead->_pLeft = LeftMost();
_pHead->_pRight = RightMost();
return true;
}
}
private:
pNode& GetRoot()
{
return _pHead->_pParent;
}
pNode LeftMost();
pNode RightMost();
private:
pNode _pHead;
};
2,检测新节点插入后,红黑树的性质是否遭到破坏;
情况一:cur为红,p为红,g为黑,u为红
情况二:cur为红,p为红,g为黑,u为黑或不存在
情况三:cur为红,p为红,g为黑,u为黑或不存在
三,红黑树的验证及删除
bool IsValidRBTree()
{
pNode pRoot = GetRoot();
if (pRoot == nullptr)
return true;
if (pRoot->_color == BLACK)
{
cout << "违反红黑树根节点必须为黑色" << endl;
return false;
}
size_t blackCount = 0;
pNode pCur = pRoot;
while (pCur)
{
if (pCur->_color == BLACK)
blackCount++;
pCur = pCur->_pLeft;
}
size_t k = 0;
return _IsValidRBTree(pRoot, k, blackCount);
}
bool _IsValidRBTree(pNode pRoot, size_t k, const size_t blackCount)
{
if (pRoot == nullptr)
{
if (blackCount != k)
{
cout << "违反性质每条路径中黑色节点个数必须相同" << endl;
return false;
}
return true;
}
if (pRoot_color == BLACK)
k++;
pNode pParent = pRoot->_pParent;
if (pParent && pParent->_color == RED && pRoot->_color == RED)
{
cout << "违反性质没有连在一起的红色节点" << endl;
return false;
}
return _IsValidRBTree(pRoot->_pLeft, k, const blackCount) &&
_IsValidRBTree(pRoot->_pRight, k, const blackCount)
}
可参考《算法导论》或《STL源码剖析》;
或参考博客,红黑树 - _Never_ - 博客园;
四,红黑树的应用
红黑树的迭代器(迭代器的好处是方便迭代)
void Increasement()
{
if (_pNode->_pRight)
{
_pNode = _pNode->_pRight;
while (_pNode->_pLeft)
{
_pNode = _pNode->_pLeft;
}
}
else
{
pNode pParent = _pNode->_pParent;
while (pParent->_pRight == _pNode)
{
_pNode = pParent;
pParent = _pNode->_pParent;
}
fi(_pNode->_pRight != pParent)
_pNode = pParent;
}
}
void Decreasement()
{
//_pNode在head的位置
if (_pNode->_pParent->_pParent == _pNode && _pNode->_color == RED)
_pNode = _pNode->_pRight;
else if(_pNode->_pLeft)
{
//_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;
}
}
改造红黑树
//因关联式容器中存储的是键值对
//K为key的类型
//ValueType, 如是map,则为pair,如是set,则为K
//KeyofValue,通过value来获得key的一个仿函数类
template
class RBTree
{
typedef RBTreeNode Node;
typedef Node* pNode;
public:
typedef RBTreeIterator Iterator;
public:
RBTree();
~RBTree();
Iterator begin() { return Iterator(_pHead->_pLeft); }
Iterator end() { return Iterator(_pHead); }
pair Insert(const ValueType& data)
{
//插入节点并调整
return make_pair(Iterator(pNewNode), true);
}
void clear();
Iterator find(const k& key);
size_t size() const;
size_t empty() const;
private:
pNode _pHead;
size_t _size;
};
set的模拟实现
template
class set
{
typedef K ValueType;
struct KeyOfValue
{
const K& operator()(const ValueType& key)
{
return key;
}
};
typedef RBTree 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() };
void clear() { return _t.clear() };
pair insert(const ValueType& data)
{
return _t.Insert(data);
}
iterator find(const K& key);
private:
RBTree _t;
}
map的模拟实现
template
class map
{
typedef pair(K, V) ValueType;
struct KeyOfValue
{
const K& operator()(const ValueType& v)
{
return v.first;
}
};
typedef RBTree 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() };
void clear() { return _t.clear() };
V& operator[](const K& key)
{
return (*(_t.Insert(ValueType(key, V())))).first).second;
}
const V& operator[](const K& key)const;
pair insert(const ValueType& data)
{
return _t.Insert(data);
}
iterator find(const K& key)
{
return _t.find(key);
}
private:
RBTree _t;
}