一、红黑树的概念
红黑树是一棵二叉搜索树,它的每个结点增加一个存储位来表示结点的颜色,可以是红色或者黑色。通过对任何一条从根到叶子路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出 2 倍,因而是接近平衡的。
1.1 红黑树的规则
- 每个结点不是红色就是黑色
- 根结点是黑色的
- 如果一个结点是红色的,则它的两个子结点必须是黑色的,也就是说任意一条路径不会有连续的红色结点。
- 对于任意一个结点,从该结点到其所有 NULL 结点的简单路径上,均包含相同数量的黑色结点(最长路径 <= 2*最短路径)
说明:《算法导论》等书籍上补充了一条每个叶子结点 (NIL) 都是黑色的规则。这里所指的叶子结点不是传统意义上的叶子结点,而是我们说的空结点,有些书籍上也把 NIL 叫做外部结点。NIL 是为了方便准确地标识出所有路径,《算法导论》在后续讲解实现的细节中也忽略了 NIL 结点,所以我们知道一下这个概念即可。
见下图,为了让上面的第三点规则更闭环一点,补充了当红色节点没有孩子结点的情况,空节点也是黑色的。

1.2 思考一下,红黑树如何确保最长路径不超过最短路径的 2 倍的?
- 由 规则 4 可知,从根到 NULL 结点的每条路径都有相同数量的黑色结点,所以极端场景下,最短路径就是全是黑色结点的路径,假设最短路径长度为 bh(black height)。
- 由 规则 2 和 规则 3 可知,任意一条路径不会有连续的红色结点,所以极端场景下,最长的路径就是一黑一红间隔组成,那么最长路径的长度为 2*bh。
- 综合红黑树的 4 点规则而言,理论上的全黑最短路径和一黑一红的最长路径并不是在每棵红黑树都存在的。假设任意一条从根到 NULL 结点路径的长度为 x,那么 bh <= x <= 2*bh。
下面是经典的红黑树,可以根据下图去更好的理解上面红黑树的规则:

1.3 红黑树的效率
假设 N 是红黑树树中结点数量,h 最短路径的长度,那么 2^h - 1 <= N < 2^(2h) - 1 , 由此推出 h ≈ logN,也就是意味着红黑树增删查改最坏也就是走最长路径 2logN,那么时间复杂度还是 O(logN)。
红黑树的表达相对 AVL 树要抽象一些,AVL 树通过高度差直观的控制了平衡。红黑树通过 4 条规则的颜色约束,间接的实现了近似平衡,他们效率都是同一档次,但是相对而言,插入相同数量的结点,红黑树的旋转次数是更少的,因为他对平衡的控制没那么严格。
二、红黑树的实现
2.1 红黑树的结构
// 枚举值表示颜色
enum Colour { RED, BLACK };
// 这里我们默认使用 key/value 结构实现
template<class K,class V>
struct {
pair<K, V> _kv;
RBTreeNode<K,V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
Colour _col;
( pair<K,V>& kv) :_kv(kv)
,_left()
,_right()
,_parent()
{ }
};
< , >
{
RBTreeNode<K, V> Node;
:
:
Node* _root;
};











