zoukankan      html  css  js  c++  java
  • 红黑树

    红黑树是一颗二叉搜索树
    1,每个节点或者是红色的或者是黑色的
    2,根节点是黑色的
    3,每个叶节点(NIL)是黑色的
    4,如果一个节点是红色的,则它的两个子节点都是黑色的
    5,对于每个节点,从该节点到其所有的后代叶节点的简单路径上,均包含相同数目的黑色节点。(黑高)
     

     旋转

    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

    插入

     

    RB_INSERT(T,z)

    y = T.til

    x = T.root

    while x != T.til

      y = x

      if z.key < x.key

      x = x.left

      else x = x.right

    z.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

    RB_INSERT_FIXUP(T, x)

    RB_INSERT_FIXUP(T,x)

    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

          z.p.p.color = RED

          y.color = BLACK

        else if z == z.p.right

          z = z.p

          LEFT_ROTATE(T,z)

        esle

          z.p.color = BLACK

          z.p.p.color = RED

          RIGHT_ROTATE(T,z)

      else (same as then clause with right and left exchanged)

    T.root.color = BLACK

      

    情况1, z的叔节点y是红色的

     情况2, z的叔节点y是黑色的,且z是一个右孩子节点

     情况3, z的叔节点y是黑色的,且z是一个左孩子节点

    情况2让z指向红色的z.p ,左旋到情况3, 在情况2和情况3 颜色不改变。 把z.p改成黑色。

    删除

    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

    一颗二叉搜索树T中删除一个节点z的整个策略有三种基本情况

    1,z没有孩子,那么简单删除它,并修改它的父节点,用Nil作为孩子来替换它

    2,z只有一个孩子,那么将孩子提升为z的位置,并修改z的父节点,用z的孩子来替换z

    3, 如果z有两个孩子,那么找z的后继y(一定是z的右子树中),并让y占据树中z的位置,z原来右子树部分成为y的新右子树,并且z的左子树成为y的新左子树

     TREE_DELETE(T,z)

    if z.left == NIL

      TRANSPLANT(T, z, z.right)

    else if z.right == NIL

      TRANSPLANT(T, z, z.left)

    else y = TREE_MINIMUM(z.right)

      if  y.p != z

        TRANSPLANT(T, y, y.right)

        y.right = z.right

        y.right.p = y

      TRANSPLANT(T, z, y)

      y.left = z.left

      y.left.p = y

     TREE_MINIMUM(x)

      while x.left != NIL

        x = x.left

      return x

    RB_DELETE(T, z)

    y = z

    y.originalcolor = y.color

    if z.left == T.nil

      x = z.right

      RB_TRANSPLANT(T,z,z.right)

    else if z.right == T.nil

      x = z.left

      RB_TRANSPLANT(T, z, z.left)

    else y = TREE_MINIMUM(z.right)

      y.originalcolor = 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.originalcolor == Black

        RB_DELETE_FIXUP(T, x)

    如果Y 是黑色的,则会产生三个问题,可以通过RB_DELETE_FIXUP进行补救。

    第一,如果y是原来的根结点。而y的一个红色的孩子成为新的根结点,这就违反了性质2

    第二,如果x,和 x.p是红色的,则违反了性质4

    第三,在树中移动y导致先前包含y的任何简单路径上黑结点个数少1,因此y的任何祖先不满足性质5

     情况1, x的兄弟节点w是红色,因为 w必须是黑颜色,所有改变w和 x.p的颜色。然后对x.p进行一次左旋。 就会将情况1,转换为2,3,4处理。这些情况由W的子节点的颜色来区分。

    情况2,x的兄弟节点为黑色,而且w的两个子节点都是黑色。因为w也是黑色的,所以从x和w上去掉一重黑色,使得x只有一重黑色,而w为红色。为了补偿从x和w去掉的一重黑色,在原来是红色或黑色的x.p

    上新增一重额外的黑色。通过将x.p作为新的节点x来重复while循环。注意到,如果通过情况1 进入到情况2,则新节点x是红黑的,因为原来的x.p是红色的。因此新的节点x.color属性值c为红色。

    情况3, x的兄弟节点w是黑色的,w的左孩子是红色的,右孩子是黑色的。交换w和左孩子的颜色,然后对w进行一次右旋。

    情况4, x的兄弟节点w是黑色的,且w的右孩子是红色的。通过进行某些颜色修改,并对x.p进行一次左旋,可以去掉x的额外黑色,从而使他变成为单重黑色。

     
  • 相关阅读:
    POJ 1300 Open Door
    POJ 2230 Watchcow
    codevs 1028 花店橱窗布置
    codevs 1021 玛丽卡
    codevs 1519 过路费
    codevs 3287 货车运输
    codevs 3305 水果姐逛水果街二
    codevs 1036 商务旅行
    codevs 4605 LCA
    POJ 1330 Nearest Common Ancestors
  • 原文地址:https://www.cnblogs.com/zhoug2020/p/9561579.html
Copyright © 2011-2022 走看看