红黑树的概念:
- 红黑树,是一种二叉搜索树,但在每个节点上增加一个存储位表示结点的颜色,可以是Red或Black。通过对任何一条从根到叶子的路径上每个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。
红黑树的性质
- 每个结点不是红色就是黑色
- 根结点是黑色的
- 如果一个结点时红色的,则它的两个孩子结点是黑色的
- 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
- 每个叶子结点都是黑色的(此处的叶子结点值的是空结点)
红黑树结点的定义
enum Color { RED, BLACK };
//红黑树结点的定义
template <class T>
class RBTreeNode {
T m_data; //结点的值域
RBTreeNode<T> * m_left;
RBTreeNode<T> * m_right;
RBTreeNode<T> * m_parent;
bool m_color; //结点的颜色
}
红黑树结构
- 为了后续实现关联式容器简单,红黑树的实现中增加一个头结点,因为根结点必须为黑色,为了与根节点进行区分,将头节点给成黑色,并且让头节点的pParent域指向红黑树的根节点,pLeft域指向红黑树中最小的结点,_pRight域指向红黑树中最大的结点,如下:
红黑树的插入操作
- 按照二叉搜索树的规则插入新节点
template<class ValueType>
class RBTree
{
//……
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:
PNode _pHead;
};
- 检测新节点插入后,红黑树的性质是否遭到破坏
因为新节点的默认颜色是红色,因此:如果其双亲结点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入结点的双亲颜色为红色时,就违反了性质三不能有连在一起的红色结点,此时需要对红黑树分情况来讨论。
红黑树与AVL树的比较
- 红黑树和AVL树都是高效平衡二叉树,增删改查的时间复杂度都是O(N),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多
红黑树的应用
- C++ STL库—map/set、mutil_map/mutil_set
- Java库
- linux内核
- 其他一些库