# 红黑树

--摘自维基百科

## 性质

这些约束强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例，这个在高度上的理论上限允许红黑树在最坏情况下都是高效的，而不同于普通的二叉查找树

## 操作

### 插入

• 性质1[1]和性质3[2]总是保持着。
• 性质4[3]只在增加红色节点、重绘黑色节点为红色，或做旋转时受到威胁。
• 性质5[4]只在增加黑色节点、重绘红色节点为黑色，或做旋转时受到威胁。

 node grandparent<span class="br0">(</span>node n<span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">return</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>

node uncle<span class="br0">(</span>node n<span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent <span class="sy0" style="color: rgb(51, 153, 51);">==</span> grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="br0">)</span>
<span class="kw1">return</span> grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="kw1">else</span>
<span class="kw1">return</span> grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>


 <span class="kw4" style="color: rgb(153, 51, 51);">void</span> insert_case1<span class="br0">(</span>node n<span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent <span class="sy0" style="color: rgb(51, 153, 51);">==</span> NULL<span class="br0">)</span>
n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="kw1">else</span>
insert_case2<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>


 <span class="kw4" style="color: rgb(153, 51, 51);">void</span> insert_case2<span class="br0">(</span>node n<span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span>
<span class="kw1">return</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span> <span class="coMULTI" style="color: rgb(128, 128, 128); font-style: italic;">/* 树仍旧有效 */</span>
<span class="kw1">else</span>
insert_case3<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>


 情形3: 如果父节点P和叔父节点U二者都是红色，(此时新插入节点N做为P的左子节点或右子节点都属于情形3,这里右图仅显示N做为P左子的情形)则我们可以将它们两个重绘为黑色并重绘祖父节点G为红色(用来保持性质5[4])。现在我们的新节点N有了一个黑色的父节点P。因为通过父节点P或叔父节点U的任何路径都必定通过祖父节点G，在这些路径上的黑节点数目没有改变。但是，红色的祖父节点G的父节点也有可能是红色的，这就违反了性质4[3]。为了解决这个问题，我们在祖父节点G上递归地进行情形1的整个过程。（把G当成是新加入的节点进行各种情况的检查）
 <span class="kw4" style="color: rgb(153, 51, 51);">void</span> insert_case3<span class="br0">(</span>node n<span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span>uncle<span class="br0">(</span>n<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">!=</span> NULL <span class="sy0" style="color: rgb(51, 153, 51);">&&</span> uncle<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> RED<span class="br0">)</span> <span class="br0">{</span>
n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
uncle<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> RED<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
insert_case1<span class="br0">(</span>grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>
<span class="kw1">else</span>
insert_case4<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>


 情形4: 父节点P是红色而叔父节点U是黑色或缺少，并且新节点N是其父节点P的右子节点而父节点P又是其父节点的左子节点。在这种情形下，我们进行一次左旋转调换新节点和其父节点的角色; 接着，我们按情形5处理以前的父节点P以解决仍然失效的性质4[3]。注意这个改变会导致某些路径通过它们以前不通过的新节点N（比如图中1号叶子节点）或不通过节点P（比如图中3号叶子节点），但由于这两个节点都是红色的，所以性质5[4]仍有效。
 <span class="kw4" style="color: rgb(153, 51, 51);">void</span> insert_case4<span class="br0">(</span>node n<span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span>n <span class="sy0" style="color: rgb(51, 153, 51);">==</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right <span class="sy0" style="color: rgb(51, 153, 51);">&&</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent <span class="sy0" style="color: rgb(51, 153, 51);">==</span> grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="br0">)</span> <span class="br0">{</span>
rotate_left<span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
n <span class="sy0" style="color: rgb(51, 153, 51);">=</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span> <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">(</span>n <span class="sy0" style="color: rgb(51, 153, 51);">==</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left <span class="sy0" style="color: rgb(51, 153, 51);">&&</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent <span class="sy0" style="color: rgb(51, 153, 51);">==</span> grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="br0">)</span> <span class="br0">{</span>
rotate_right<span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
n <span class="sy0" style="color: rgb(51, 153, 51);">=</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>
insert_case5<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>

 情形5: 父节点P是红色而叔父节点U 是黑色或缺少，新节点N 是其父节点的左子节点，而父节点P又是其父节点G的左子节点。在这种情形下，我们进行针对祖父节点G 的一次右旋转; 在旋转产生的树中，以前的父节点P现在是新节点N和以前的祖父节点G 的父节点。我们知道以前的祖父节点G是黑色，否则父节点P就不可能是红色 (如果 P 和 G 都是红色就违反了性质4，所以 G 必须是黑色)。我们切换以前的父节点P和祖父节点G的颜色，结果的树满足性质4[3]。性质5[4]也仍然保持满足，因为通过这三个节点中任何一个的所有路径以前都通过祖父节点G ，现在它们都通过以前的父节点P。在各自的情形下，这都是三个节点中唯一的黑色节点。
 <span class="kw4" style="color: rgb(153, 51, 51);">void</span> insert_case5<span class="br0">(</span>node n<span class="br0">)</span> <span class="br0">{</span>
n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> RED<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="kw1">if</span> <span class="br0">(</span>n <span class="sy0" style="color: rgb(51, 153, 51);">==</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left <span class="sy0" style="color: rgb(51, 153, 51);">&&</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent <span class="sy0" style="color: rgb(51, 153, 51);">==</span> grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="br0">)</span> <span class="br0">{</span>
rotate_right<span class="br0">(</span>grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span>
<span class="coMULTI" style="color: rgb(128, 128, 128); font-style: italic;">/* Here, n == n->parent->right && n->parent == grandparent(n)->right */</span>
rotate_left<span class="br0">(</span>grandparent<span class="br0">(</span>n<span class="br0">)</span><span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>
<span class="br0">}</span>


### 删除

<span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>
sibling<span class="br0">(</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>n<span class="br0">)</span>
<span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span>n <span class="sy0" style="color: rgb(51, 153, 51);">==</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="br0">)</span>
<span class="kw1">return</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="kw1">else</span>
<span class="kw1">return</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>


<span class="kw4" style="color: rgb(153, 51, 51);">void</span>
delete_one_child<span class="br0">(</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>n<span class="br0">)</span>
<span class="br0">{</span>
<span class="coMULTI" style="color: rgb(128, 128, 128); font-style: italic;">/*
* Precondition: n has at most one non-null child.
*/</span>
<span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>child <span class="sy0" style="color: rgb(51, 153, 51);">=</span> is_leaf<span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">?</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left <span class="sy0" style="color: rgb(51, 153, 51);">:</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">;</span>

replace_node<span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">,</span> child<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="kw1">if</span> <span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span>child<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> RED<span class="br0">)</span>
child<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="kw1">else</span>
delete_case1<span class="br0">(</span>child<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>
<span class="kw3">free</span><span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>


<span class="kw4" style="color: rgb(153, 51, 51);">void</span>
delete_case1<span class="br0">(</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>n<span class="br0">)</span>
<span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent <span class="sy0" style="color: rgb(51, 153, 51);">!=</span> NULL<span class="br0">)</span>
delete_case2<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>


 情况 2: S 是红色。在这种情况下我们在N的父亲上做左旋转，把红色兄弟转换成N的祖父。我们接着对调 N 的父亲和祖父的颜色。尽管所有的路径仍然有相同数目的黑色节点，现在 N 有了一个黑色的兄弟和一个红色的父亲，所以我们可以接下去按 4、5或6情况来处理。(它的新兄弟是黑色因为它是红色S的一个儿子。)
<span class="kw4" style="color: rgb(153, 51, 51);">void</span>
delete_case2<span class="br0">(</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>n<span class="br0">)</span>
<span class="br0">{</span>
<span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>s <span class="sy0" style="color: rgb(51, 153, 51);">=</span> sibling<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>

<span class="kw1">if</span> <span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> RED<span class="br0">)</span> <span class="br0">{</span>
n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> RED<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="kw1">if</span> <span class="br0">(</span>n <span class="sy0" style="color: rgb(51, 153, 51);">==</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="br0">)</span>
rotate_left<span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="kw1">else</span>
rotate_right<span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>
delete_case3<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>

 情况 3: N 的父亲、S 和 S 的儿子都是黑色的。在这种情况下，我们简单的重绘 S 为红色。结果是通过S的所有路径，它们就是以前不通过 N 的那些路径，都少了一个黑色节点。因为删除 N 的初始的父亲使通过 N 的所有路径少了一个黑色节点，这使事情都平衡了起来。但是，通过 P 的所有路径现在比不通过 P 的路径少了一个黑色节点，所以仍然违反属性4。要修正这个问题，我们要从情况 1 开始，在 P 上做重新平衡处理。
<span class="kw4" style="color: rgb(153, 51, 51);">void</span>
delete_case3<span class="br0">(</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>n<span class="br0">)</span>
<span class="br0">{</span>
<span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>s <span class="sy0" style="color: rgb(51, 153, 51);">=</span> sibling<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>

<span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span>
s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> RED<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
delete_case1<span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span> <span class="kw1">else</span>
delete_case4<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>

 情况 4: S 和 S 的儿子都是黑色，但是 N 的父亲是红色。在这种情况下，我们简单的交换 N 的兄弟和父亲的颜色。这不影响不通过 N 的路径的黑色节点的数目，但是它在通过 N 的路径上对黑色节点数目增加了一，添补了在这些路径上删除的黑色节点。
<span class="kw4" style="color: rgb(153, 51, 51);">void</span>
delete_case4<span class="br0">(</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>n<span class="br0">)</span>
<span class="br0">{</span>
<span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>s <span class="sy0" style="color: rgb(51, 153, 51);">=</span> sibling<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>

<span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> RED<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span>
s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> RED<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span> <span class="kw1">else</span>
delete_case5<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>

 情况 5: S 是黑色，S 的左儿子是红色，S 的右儿子是黑色，而 N 是它父亲的左儿子。在这种情况下我们在 S 上做右旋转，这样 S 的左儿子成为 S 的父亲和 N 的新兄弟。我们接着交换 S 和它的新父亲的颜色。所有路径仍有同样数目的黑色节点，但是现在 N 有了一个右儿子是红色的黑色兄弟，所以我们进入了情况 6。N 和它的父亲都不受这个变换的影响。
<span class="kw4" style="color: rgb(153, 51, 51);">void</span>
delete_case5<span class="br0">(</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>n<span class="br0">)</span>
<span class="br0">{</span>
<span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>s <span class="sy0" style="color: rgb(51, 153, 51);">=</span> sibling<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>

<span class="kw1">if</span>  <span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span> <span class="br0">{</span> <span class="coMULTI" style="color: rgb(128, 128, 128); font-style: italic;">/* this if statement is trivial,
due to Case 2 (even though Case two changed the sibling to a sibling's child,
the sibling's child can't be red, since no red parent can have a red child). */</span>
<span class="co1" style="color: rgb(102, 102, 102); font-style: italic;">// the following statements just force the red to be on the left of the left of the parent, </span>
<span class="co1" style="color: rgb(102, 102, 102); font-style: italic;">// or right of the right, so case six will rotate correctly.</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>n <span class="sy0" style="color: rgb(51, 153, 51);">==</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> RED<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span> <span class="co1" style="color: rgb(102, 102, 102); font-style: italic;">// this last test is trivial too due to cases 2-4.</span>
s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> RED<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
rotate_right<span class="br0">(</span>s<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span> <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>n <span class="sy0" style="color: rgb(51, 153, 51);">==</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> BLACK<span class="br0">)</span> <span class="sy0" style="color: rgb(51, 153, 51);">&&</span>
<span class="br0">(</span>s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">==</span> RED<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span><span class="co1" style="color: rgb(102, 102, 102); font-style: italic;">// this last test is trivial too due to cases 2-4.</span>
s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> RED<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
rotate_left<span class="br0">(</span>s<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>
<span class="br0">}</span>
delete_case6<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>

 情况 6: S 是黑色，S 的右儿子是红色，而 N 是它父亲的左儿子。在这种情况下我们在 N 的父亲上做左旋转，这样 S 成为 N 的父亲和 S 的右儿子的父亲。我们接着交换 N 的父亲和 S 的颜色，并使 S 的右儿子为黑色。子树在它的根上的仍是同样的颜色，所以属性 3 没有被违反。但是，N 现在增加了一个黑色祖先: 要么 N 的父亲变成黑色，要么它是黑色而 S 被增加为一个黑色祖父。所以，通过 N 的路径都增加了一个黑色节点。 此时，如果一个路径不通过 N，则有两种可能性: 它通过 N 的新兄弟。那么它以前和现在都必定通过 S 和 N 的父亲，而它们只是交换了颜色。所以路径保持了同样数目的黑色节点。它通过 N 的新叔父，S 的右儿子。那么它以前通过 S、S 的父亲和 S 的右儿子，但是现在只通过 S，它被假定为它以前的父亲的颜色，和 S 的右儿子，它被从红色改变为黑色。合成效果是这个路径通过了同样数目的黑色节点。 在任何情况下，在这些路径上的黑色节点数目都没有改变。所以我们恢复了属性 4。在示意图中的白色节点可以是红色或黑色，但是在变换前后都必须指定相同的颜色。
<span class="kw4" style="color: rgb(153, 51, 51);">void</span>
delete_case6<span class="br0">(</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>n<span class="br0">)</span>
<span class="br0">{</span>
<span class="kw4" style="color: rgb(153, 51, 51);">struct</span> node <span class="sy0" style="color: rgb(51, 153, 51);">*</span>s <span class="sy0" style="color: rgb(51, 153, 51);">=</span> sibling<span class="br0">(</span>n<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>

s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>

<span class="kw1">if</span> <span class="br0">(</span>n <span class="sy0" style="color: rgb(51, 153, 51);">==</span> n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="br0">)</span> <span class="br0">{</span>
s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>right<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
rotate_left<span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span>
s<span class="sy0" style="color: rgb(51, 153, 51);">-></span>left<span class="sy0" style="color: rgb(51, 153, 51);">-></span>color <span class="sy0" style="color: rgb(51, 153, 51);">=</span> BLACK<span class="sy0" style="color: rgb(51, 153, 51);">;</span>
rotate_right<span class="br0">(</span>n<span class="sy0" style="color: rgb(51, 153, 51);">-></span>parent<span class="br0">)</span><span class="sy0" style="color: rgb(51, 153, 51);">;</span>
<span class="br0">}</span>
<span class="br0">}</span>


## 渐进边界的证明

• h(v) = 以节点v为根的子树的高度。
• bh(v) = 从v到子树中任何叶子的黑色节点的数目(如果v是黑色则不计数它)(也叫做黑色高度)。

$2^{bh(v)}-1 = 2^{0}-1 = 1-1 = 0$

$2^{bh(v')-1}-1 + 2^{bh(v')-1}-1 + 1 = 2^{bh(v')}-1$

$n \geq 2^{{h(root) \over 2}} - 1 \leftrightarrow \; \log{(n+1)} \geq {h(root) \over 2} \leftrightarrow \; h(root) \leq 2\log{(n+1)}$

## 注释

1. ^ 性质1. 节点是红色或黑色。
2. ^ 性质3. 所有叶子都是黑色。
3. 3.0 3.1 3.2 3.3 3.4 性质4. 每个红色节点的两个子节点都是黑色。
4. 4.0 4.1 4.2 4.3 4.4 4.5 性质5. 从每个叶子到根的所有路径都包含相同数目的黑色节点。
5. ^ 性质2. 根是黑色。

## 外部链接

• 本文已收录于以下专栏：

举报原因： 您举报文章：红黑树 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)