基本定义
红黑树是在二叉搜索树的基础上额外添加了颜色属性,它具有以下的性质
1、红黑树的节点只有红和黑2种颜色
2、红黑树的根节点为黑色
3、如果一个节点是红色的,那么它的2个子节点为黑色
4、叶子节点为T.NIL,颜色为黑色
5、对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
分析
假设现在有一棵已经建好的红黑树T,现在要往其中插入一个新的节点z,毫无疑问,肯定是先按照二叉搜索树的插入方法先将z插入到树中。之后,因为是红黑树,要满足上述5条性质,就必然要对这棵二叉搜索树的颜色进行修改。那么修改的方法是什么呢?
首先考虑当z插入二叉树以后,可能会出现哪些情况?首先z如果不是根节点的话就是叶子节点,根节点的情况是最简单的,直接设置它的颜色属性为黑色即可。
现在来考虑叶子节点的情况。首先,先考虑将z的颜色设置为什么最好,由性质5可以看出,黑色节点的数量会决定这棵红黑树是否合法,那么为了避免麻烦,直接将z设置为红色显然最好。现在来考虑下z的父节点的情况。如果z的父节点为黑色,符合性质3,不用再进行修改。相反,如果z的父节点为红色,此时需要对z的父节点修改颜色。
为了方便起见,设节点x的父节点为x.p,x的左孩子为x.left,x的右孩子为x.right。x的颜色属性设为x.color,红色为R,黑色为B。
由性质3可知z.p.p.color=B(z节点的父节点为红色,则它的祖先节点必然为黑)。因为其他没有添加z节点的子树必然是合法的红黑树,所以现在只看根节点为z.p.p的这棵子树。根据性质1可知,z.p.p除z外的另一个子节点只有2种颜色(黑色或者红色)。显然,红色是最简单的情况,毕竟红黑树对每条路径的红色节点数没有任何限制。那么现在这棵以z的祖父节点为根的红黑树唯一不符合上述5条性质的只有z和z.p节点。因为z节点的颜色已经为红了,那么考虑将z.p设置为黑色,但是z.p这条路径的黑色节点数量就会增加,所以z的叔节点也要变为黑色,此时z.p.p子树的每一条路径的黑色节点数量都增加了1,它自身必须变为红色来维持黑色节点的数量,使其始终满足性质5。
那么如果z的叔节点为黑呢?因为要维持性质5,肯定不能像刚才那种情况那样,很无脑的改变z.p.p的2个子树上的黑色节点数量。还有一种选择,就是通过旋转某个节点,使z.p.p的子树符合红黑树的特征。既然要旋转,肯定要考虑z的左右位置,如果z是右孩子,直接左转一次,使其变为左孩子即可。现在只要思考z为左孩子时,要旋转哪个节点。继续旋转z节点是无意义的。继续找,可以发现右旋z.p,并将z.p变为黑色,z.p.p变为红色可以符合红黑树的特征。
总结
综上所述,向一棵红黑树中插入一个新节点,共有4种情况,其中有2种情况可以合并,分别是:
1、红黑树为空,z为根节点。
2、红黑树不为空,z的叔节点为红,直接将z.p,z的叔节点变为黑,z.p.p变为红
3、红黑树不为空,z的叔节点为黑,z为右孩子,先左旋,之后参照情况4
4、直接将z.p右旋,z.p变为黑色,z.p.p变为红色