1、红黑树的限制条件
1)红黑树的节点是有颜色的,红色或者黑色
2)根节点是黑色的
3)每个叶子节点(叶节点即指树尾端NIL指针或NULL节点)是黑色的
4)如果一个节点是红色的,那么它的两个子节点都是黑色的;推论,不存在两个红色节点是相邻的。
5)从一个节点开始到每个叶子节点的简单路径上面的黑色节点的数量相同
2、红黑树的插入
1)旋转
a,左旋:以当前节点P和其右子节点Pr之间的“链”为轴逆时针旋转,当前节点P下降,其右子树上升,Pr取代P,当前节点成为其原右子节点Pr的左子节点,Pr的左子树挂接为P的右子树。
b.右旋:以当前节点P和其左子节点Pl之间的“链”为轴顺时针旋转,当前节点P下降,其左子树上升,Pl取代P,当前节点成为其原左子节点Pl的右子节点,Pl的右子树挂接为P的左 子树。
2)插入
插入分为两步:1,像二叉平衡树那样插入节点;2,插入后修复
a.第一步插入,分为2种情况:空树,插入为根节点,颜色为黑色;非空树,递归比较应该插入左子树还是右子树.
b.插入后修复,插入一个节点后,该节点一定是处于某个叶子节点(这里是非NIL的叶子),而且要涂色;当前节点为跟节点的话,必须得涂成黑色,以符合规则2,非根节点若涂成黑色肯定要违反规则5,若涂成红色,在其父节点为黑色时不会违反任何规则,那么需要修复的情况就是其父节点为红色的情况。所以我们选择在插入时涂为红色。
即有两种情况需要修复:1)空树插入,违反规则2;2)其父节点为红色,违反规则4。
需要修复的第二种情况,其祖父节点一定为黑色(否则违反规则4)根据具体情况分为3种:1)其同祖父的另一子节点(叔叔节点)为红色,当前节点(即插入节点)为父节点的左节点或右节点;2)叔叔节点为黑色,当前节点为父节点的左节点;3)叔叔节点为黑色,当前节点为父节点的右子点。2)、3)是 默认在祖父节点的左边,右边原理相同。
第一种情况下,只要将祖父节点的黑色下移,就可以解决,即父节点和叔叔节点修为黑色,祖父节点修为红色,那么对于上层来说有同样的需要修复的问题。第二种情况下,把父节点修为黑色,祖父节点修为红色,然后祖父节点右旋,这时整个子树对外的表现就没有变化了。第三种情况,父节点先左旋,转换为第二种情况,然后再修复,不能直接用第二种情况的方法修复,因为当前节点有可能是1和3这两种修复过程中出现变红。从上面分析可以得出,插入一个节点,连续修复,直到出现第二种情况或者达到根节点就修复完成。
1、 黑 2、 黑 3、 黑
红 红 红 黑 红 黑
红 红 红
在这里可以看出,红黑树的5个限制条件既能保证红黑树的查找效率,也能保证能够修复。
3、红黑树的删除--以中序遍历为出发点(二叉查找树的性质决定的)
分为两步:1、以二叉查找树的方法删除节点,2、修复红黑树
二叉查找树删除节点:
1)无非空子节点,直接删除,空节点代替之;2)有一个非空子节点,删除后子节点代替之;3)有两个非空子节点,删除,以其后继(或前驱)代替之,然后再递归删除其后继(前驱),其后继(前驱)不会有两个非空子节点,所以只传递一次。
==========================================================================================
二叉查找树的删除
继续讲解之前,补充说明下二叉树结点删除的几种情况,待删除的结点按照儿子的个数可以分为三种:
- 没有儿子,即为叶结点。直接把父结点的对应儿子指针设为NULL,删除儿子结点就OK了。
- 只有一个儿子。那么把父结点的相应儿子指针指向儿子的独生子,删除儿子结点也OK了。
- 有两个儿子。这是最麻烦的情况,因为你删除结点之后,还要保证满足搜索二叉树的结构。其实也比较容易,我们可以选择左儿子中的最大元素或者右儿子中的最小元素放到待删除结点的位置,就可以保证结构的不变。当然,你要记得调整子树,毕竟又出现了结点删除。习惯上大家选择左儿子中的最大元素,其实选择右儿子的最小元素也一样,没有任何差别,只是人们习惯从左向右。这里咱们也选择左儿子的最大元素,将它放到待删结点的位置。左儿子的最大元素其实很好找,只要顺着左儿子不断的去搜索右子树就可以了,直到找到一个没有右子树的结点。那就是最大的了。
===========================================================================================