主要包含五个属性:color、key、left、right 和 p 。如果一个结点没有子节点或者是父结点,则该结点相应的指针属性的值为NIL。红黑树有以下性质:
每个节点或是红色的,或是黑色的。
根节点是黑色的。
每个叶结点(NIL)是黑色的。
如果一个结点是红色的,则他的两个子结点都是黑色的。
对每个结点,从该结点到其所有的后代叶结点的简单路径上,均包含相同数目的黑色结点。
从某个结点 x 出发(不包含该结点)到达一个叶结点的任意一条简单路径上的黑色结点的个数称为该结点的黑高(black-height),记为 。根据第5条性质,从这一条出发,可以得出,从结点 x 到所有的后代叶结点黑高是相同的。于是定义红黑树的黑高就是根结点的黑高。
引理 1: 一棵有个内部结点的红黑树的高度至多为
证明: 第一步证明,任意 x 结点为根的子树中至少包含 内部结点。使用数学归纳法:
① 当 x 为 NIL 的时候, 为 0 ,则红黑树没有内部结点,结论成立。
② 当 x 为任意一个结点 k 时, 则有
x 为 k 的子结点的时候, 有两种取值的可能性,和,主要取决于子结点的颜色。因为求最少的所以取 ,得到:
()()
③ 假设成立。
第二步,证明一棵有个内部结点的红黑树的高度至多为。
④ 假设树高为 h ,因为红黑树的性质 4 ,所以可以得出至少有一半层为黑色结点,即 。
⑤ 代入第一步的结论,有 ,同时取对数不影响单调性,得到 ,最终化简得到:
⑥ 证明完毕
lzk_baggk:主要思路来自算法导论。由于树的基本操作的时间的复杂度都是由树的高度来确定的。所以可以推出是在级别的。
对于红黑树的二叉搜索树的一种,对于搜索、遍历等操作和搜索树没有什么区别。但是插入删除等操作可能会破坏红黑树的性质呢。需要其他的补充操作。
所有的插入操作分为三个部分,按照正常的搜索树的插入结点,然后再将插入结点标记为红色,最后进行调整。
lzk_baggk:修复的操作在一个循环里面。算法本身是保障每次的操作只有性质4被破坏了。然后向上修复。插入的子结点为根的子树是符合红黑树的定义的。
搜索树正常插入
// 1. 找到插入的位置 // 2. 插入,并且设置颜色为红色 // 3. 调整如果树为空的话,则将颜色标记为黑色。如果父结点为黑色,则不需要任何调整。如果为红色,当叔结点为红色的时候,只需要将父结点与叔结点调整为黑色,并且把祖父结点调整为红色则好。如果叔结点为黑色,则需要考虑插入结点的位置。如果在父结点的右侧,则需要先左旋转,再右旋转。如果直接在左侧,则直接右旋转。
调整