首页 > 技术文章 > 红黑树

zhoug2020 2018-08-30 17:37 原文

红黑树是一颗二叉搜索树
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的额外黑色,从而使他变成为单重黑色。

 

 

 

 

 

推荐阅读