一、红黑树的概念
红黑树是一种自平衡的二叉查找树,是在计算机科学中使用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由鲁道夫·贝尔发明,它称之为“对称二叉B树”,它现代的名字是在Leo J.Guibas和Robert Sedgewick于1978年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的:它可以在 O ( l o g n ) O(logn) O(logn)时间内做查找、插入和删除,这里的 n n n是树中元素的数目。——摘自维基百科
二、红黑树的性质
- 根节点是黑色的。
- 节点是黑色的或者红色的。
- 所有的叶子节点都是黑色的(叶子节点为NIL)。
- 每个红色节点的两个子节点都是黑色的(从每个叶子节点到根节点的所有路径上不能有两个连续的红色节点)。
- 从任一节点到其每个叶子节点的所有简单路径上都包含相同数目的黑色节点。
三、 红黑树的操作
3.1 左旋
3.2 右旋
3.3 插入
往一颗红黑树插入节点时,一般都是假设待插入的节点为红色。之所以不设置成黑色是因为插入黑色节点会直接破坏性质5,而插入红色节点虽然可能会破坏性质4,但是可以通过变色或者旋转来使红黑树重新恢复性质。
当往一颗红黑树插入红色节点时,会有以下几种情况发生:
PS:N表示插入节点,P表示插入节点的父节点,G表示插入节点的祖父节点,S表示插入节点的父节点的兄弟节点(插入节点的叔父节点)
-
红黑树中没有节点,此时插入的节点即为根节点,则直接将插入的节点设置成根节点并将颜色设置成黑色即可。
-
插入节点的父节点为黑色节点,此时红黑树满足所有性质,因此不用做调整。
-
插入节点的父节点为红色节点,此时会破坏性质4,因此插入节点之后需要对红黑树进行调整,由以下几种情况发生:
3.1 插入节点的父节点的兄弟节点(插入节点的叔父节点)为红色,此时插入节点的祖父节点必为黑色,因此可以将父节点和叔父节点设置成黑色,将祖父节点设置成红色来达到满足红黑树的性质。这么做之后祖父节点可能跟其父节点冲突(破坏性质4),因此需要将当前节点指向祖父节点,再对祖父节点进行处理(参考3.2和3.3)。
3.2 插入节点位于其父节点的左边,且父节点位于祖父节点的左边(父节点位于祖父节点的右边可以参照左边做对应处理),父节点的兄弟节点(插入节点的叔父节点)为黑色,这种情况可以将父节点设置成黑色,祖父节点设置成红色,并对父节点右旋来达到满足红黑树性质的要求。
3.3 插入节点位于其父节点的右边,且父节点位于祖父节点的左边(父节点位于祖父节点的右边可以参照左边做对应处理),父节点的兄弟节点(插入节点的叔父节点)为黑色,这种情况可以先对父节点进行左旋,再参照3.2进行处理。
3.4 删除
删除一个节点时,主要有以下3种情况:删除节点没有非空的子节点(NIL节点)、删除节点有一个非空的子节点、删除节点有两个非空的子节点。其中,当删除节点有两个非空的子节点时,可以找到删除节点的直接前驱(左子树中小于删除节点的最大节点)或直接后继(右子树中小于删除节点的最小节点),将直接前驱或直接后继的值覆盖删除节点的值,然后考虑如何删除直接前驱或直接后继即可(这样子,可以将问题转变成“删除节点有一个非空的子节点”的情况,因为直接前驱或直接后继最多只会有一个非空的子节点)。
对上面的情况进行归纳:当删除一个节点时,删除节点最多有一个非空的子节点,对此,会发生如下几种情况:
PS:N表示待删除的节点,P表示N的父节点,S表示N的兄弟节点,SL表示S的左子节点,SR表示S的右子节点。
- N为根节点,此时直接删除节点即可。
- N为红色节点, 则该节点没有非空的叶子节点,否则不满足性质4和性质5,所以直接删除N即可。
- N为黑色节点,此时N肯定存在兄弟节点,否则不满足性质5,因此会有以下几种情况(以下几种情况都假设N为P的左子节点,当N为P的右子节点时可以参照调整):
3.1 N的兄弟节点S为红色,则其父节点P为黑色,且删除节点的兄弟节点有两个非空的黑色子节点(SL和SR),否则不满足性质4和性质5。因此,可以将S设置成黑色,将SL设置成红色,再对P左旋即可。
3.2 N的兄弟节点S为黑色,且S没有非空的子节点(两个黑色的NIL节点),此时将S设置成红色,则所有通过P的路径会比不通过P的路径少一个黑色节点,因此将当前节点指向P,再对P进行调整,直到根节点为止。
3.3 N的兄弟节点S为黑色,且S的左子节点SL为红色,此时N的父节点P的颜色是不确定的,因此可以将SL设置成P的颜色,将P设置成黑色,再对S右旋,接着再对SL左旋即可。
3.3 N的兄弟节点S为黑色,且S的右子节点SR为红色,此时N的父节点P的颜色是不确定的,因此可以将S设置成P的颜色,将P设置成黑色,将SR设置成黑色,再对S左旋即可。