第 13 章 红黑树

  二叉搜索树在树的高度较高时,动态集合的操作可能并不比在链表上执行的快。红黑树是许多“平衡”搜索树的一种,可以保证在最坏情况下基本动态集合操作的时间复杂度为O(lgn)。
  

13.1 红黑树的性质

  红黑树是一颗二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是RED或BLACK。通过对任何一条从根到叶子的简单路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出 2 倍,因而是近似于平衡的
  树中每个结点包含 5 个属性:color、key、left、right和p。如果一个结点没有子结点或父结点,则该结点相应指针属性的值为NIL。可以把这些NIL视为指向二叉搜索树的叶结点(外部结点)的指针,而把带关键字的结点视为树的内部结点。
  一颗红黑树是满足下面红黑性质的二叉搜索数:
  

  1. 每个结点或是红色的,或是黑色的。
  2. 根结点是黑色的。
  3. 每个叶结点(NIL)是黑色的。
  4. 如果一个结点是红色的,则它的两个子节点是黑色的。
  5. 对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点。
      为了便于处理红黑树代码中的边界条件,使用一个哨兵来代表NIL。对于一颗红黑树 T,哨兵 T.nil是一个与树中普通结点有相同属性的对象。它的color属性为BLACK,而其他属性可以为任意值。使用一个哨兵 T.nil来代表说有的NIL:所有的叶节点和根节点的父节点。
      从某个结点 x 出发(不含该结点)到达一个叶结点的任意一条简单路径上的黑色结点个数称为该结点的黑高,记为bh(x)。黑高的概念是明确定义的,因为从该结点出发的所有下降到其叶结点的简单路径的黑结点个数都相同。于是,定义红黑树的黑高为其根节点的黑高。
      引理13.1 一颗有 n 个内部结点的红黑树的高度至多为2lg(n+1)。
      由该引理可知,动态集合操作可在红黑树上在O(lgn)时间内执行。因为这些操作在一颗高度为 h 的二叉搜索树上的运行时间为O(h),而任何包含 n 个结点的红黑树又都是高度为O(lgn)的二叉搜索树。

13.2 旋转

  搜索数操作TREE-INSERT和TREE-DELETE在含 n 个关键字的红黑树上,运行花费时间为O(lgn),由于这两个操作对数做了修改,结果可能违反红黑树性质。,为了维护这些性质,必须要改变树中某些结点的颜色以及指针结构。
  指针结构的修改是通过旋转来完成的,这是一种能保持二叉搜索树性质的搜索树局部操作。包括两种旋转:左旋和右旋。当在某个结点 x 上做左旋时,假设它的右孩子为 y 而不是T.nil; x 可以为其右孩子不是T.nil结点的树内任意结点。 左旋以 x 到 y 的链为“支轴”进行。它使 y 成为该子树新的根结点,x 成为 y 的左孩子,y 的左孩子成为 x 的右孩子。
  这里写图片描述
  旋转保持了二叉搜索树的性质。在LEFT-ROTATE的伪代码中,假设x.right != T.nil 且根节点的父结点为T.nil。
  LEFT-ROTATE(T,x)
  

y = x.right
x.right = y.left
if y.left != T.nil
    y.left.p = x
y.p = x.p
if x.p == T.nil
    T.root = y
else if x == x.p.left
    x.p.left = y
else x.p.right = y
y.left = x
x.p = y

LEFT-RATATE在O(1)时间内完成。在旋转操作中,只有指针改变,其他所有属性都保持不变。

13.3 插入

  可以在O(lgn)时间内完成向一颗含 n 个结点的红黑树中插入一个新结点。调用 RB-INSERT(T,z)在红黑树 T 内插入结点 z,假设 z 的key属性已被实现赋值。调用辅助程序RB-INSERT-FIXUP来对结点重新着色并旋转,以保持红黑树性质。
RB-INSERT(T,z)

y = T.nil
x = T.root
while x != T.nil
    y = x
    if z.key < x.key
    x = x.left
    else x = x.right
a.p = y
if y == T.nil
    T.root = z
else if z.key < y.key
    y.left = z
else y.right = z
z.left = T.nil
z.right = T.nil
z.color = RED
RB-INSERT-FIXUM(T,z)

RB-INSERT-FIXUP(T,z)

while z.p.color == RED
    if z.p == z.p.p.left
        y = z.p.p.right
        if y.color == RED
            z.p.color = BLACK
            y.color = BLACK
            z.p.p.color = RED
            z = z.p.p
        else if z == z.p.right
            z = z.p
            LEFT-ROTATE(T, z)
        z.p.color = BLACK
        z.p.p.color = RED
        RIGHT-ROTATE(T, z.p.p)
    else (same as then clause
            with "right“ and "left" exchanged)
T.root.color = BLACK    

13.4 删除

  红黑树删除一个结点要花费O(lgn)时间。与插入操作相比,删除操作要复杂。
  首先定义一个子过程RB-TRANSPLANT:
  
RB-TRANSPLANT(T, u, v)

if u.p == T.nil
    T.root = v
else if u == u.p.left
    u.p.left = v
else u.p.right = v
v.p = u.p

RB-DELETE(T, z)

y = z
y-original-color = y.color
if z.left == T.nil
    x = z.right
    RB-TRANSPLANT(T,z, z.right)
else if z.right == T.nil
    x = z.right
    RB-TRANSPLANT(T, z, z.left)
else y = TREE-MINIMUM(z.right)
    y-original-color = y.color
    x = y.right
    if y.p == z
        x.p = y
    else RB-TRANSPLANT(T, y, y.right)
        y.right = z.right
        y.right.p = y
    RB-TRANSPLANT(T, z, y)
    y.left = z.left
    y.left.p = y
    y.color = z.color
if y-original-color == BLACK
    RB-DELETE-FIXUP(T,x)

RB-DELETE调用一个辅助过程RB-DELETE-FIXUP,该过程通过改变颜色和执行旋转来恢复红黑性质。
RB-DELETE-FIXUP(T,x)

while x != T.root and x.color == BLACK
    if x == x.p.left
        w = x.p.right
        if w.color == RED
            w.color = BLACK
            x.p.color = RED
            LEFT-ROTATE(T, x.p)
            w = x.p.right
        if w.left.color == BLACK and w.right.color == BLACK
            w.color = RED
            x = x.p
        else if w.right.color == BLACK
                w.left.color = BLACK
                w.color = RED
                RIGHT-ROTATE(T, w)
                w = x.p.right
            w.color = x.p.color
            x.p.color = BLACK
            w.right.color = BLACK
            LEFT-ROTATE(T,x.p)
            x = T.root
    else(same as then clause with "right" and "left" exchanged)
x.color = BLACK
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值