红黑树定义
红黑树(Red Black Tree) 是一种自平衡的二叉查找树,典型用途是实现关联数组,红黑树与AVL树类似,都是在插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。
红黑树查找、插入删除的时间复杂度为O(logn)
下图是一棵红黑树:
红黑树性质
红黑树是每个节点都带有颜色属性的二叉查找树,颜色是红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
- 每个节点是红色或黑色
- 根节点时黑色
- 哨兵节点是黑色(且每个叶节点都要指向一个哨兵节点,哨兵节点一定是黑的)
- 每个红色节点的两个子节点是黑色。(从每个节点到根的所有路径上,不能有两个连续的红色节点)
- 从任一节点到其叶子节点的所有路径都包含相同数据的黑色节点
这些约束强制了红黑树的关键性质:从根到叶子的最长路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的
在二叉树中,每次插入的节点都是红色,至于该节点最后是什么颜色,取决于把不同的情况。
红黑树的插入
红黑树的插入,每次新插入的节点都是红色的,但是最终是什么颜色,取决于以下情况:
记要插入的节点为:p
① 如果p是第一个节点,根据红黑树性质:根节点必须为黑色。所以该节点的颜色为黑色。
② 若p的双亲节点的颜色为红色,则需要通过旋转或者着色的方式,进行红黑树的调整。
注意,这里又分为两种情况:(1).若p插入到双亲节点的右侧。 (2) 若p插入双亲节点的左侧。
通过以上方式,我们可以进行红黑树的调整,可是我们如何知道什么情况下使用旋转的方式,什么情况下使用着色的方式呢?
- 当p的双亲的双亲的左(右)孩子为红色时,我们通过着色的方式,进行调整,即让p的双亲的双亲的左右孩子变为红色,p的双亲的双亲变为黑色,这样我们就能保证,在红黑树的每一条路径上的黑节点的个数都是相等的。
- 当p的双亲的双亲的左(右)孩子为黑色时,我们通过旋转的方式,进行调整。有可能是双旋转,也有可能是单旋转,这取决于p插入在其直接双亲节点和p双亲的双亲节点的颜色,从而达到每一条路径上的黑节点个数是相等的。
我们上述所说的p双亲的双亲的左(右)孩子,这个左和右,说的是从整体上看,p在红黑树的左边插入还是右边插入,如果是从左边插入,则找的几居室双亲的双亲的右孩子,反之亦然。
示例:
注意:p指向的是待插入节点,在演示的过程中,前面的没有将哨兵节点截进图内,但是一定要清楚,每一个新插入的节点的左右孩子最开始都是指向哨兵节点的。且哨兵节点一定是黑色的。
① 现在p是值为12的节点,插入后发现p是根节点,所以p的颜色必须为黑色。
② 现在p是值为23的节点,它应该插入12的右侧。p的父节点是黑色,且每条路径上的节点数相同,也没有出现一条路径上同时出现连续两个红色节点的情况,所以正常插入(新插入的节点都是红色的)。如下图:
③ 现在p是值为34的节点,应该插入23的右侧。 p(34)的父节点为红色,此时出现了连续两个红节点的情况,这个时候,我们就需要看p的双亲的双亲节点的左孩子节点是什么颜色,我们知道,此时12这个节点的左孩子是哨兵节点,而哨兵节点是黑色的,所以我们要通过旋转的方式,调整这棵红黑树。我们发现,p(34)和23、12这三个节点在同一直线上,所以采用左单旋转的方式进行调整,调整后,为了保持在每一条路径上黑色节点的个数相同,我们需要将p的双亲节点置为黑色,把p的双亲的双亲节点置为红色。如下图:
④ 现在p是值为56的节点,应该插入34的右侧。p(56)的父节点为红色,此时又出现了同一路径上连续两个红节点的情况,这个时候,我们又要去看p的双亲的双亲节点(即23这个节点)的左孩子节点是什么颜色ÿ