K:红黑树

  红黑树由AVL树改进而来,红黑树与AVL都是平衡结构的树。对于AVL树,其每次插入操作都需要从根节点处开始判断该树是否失去平衡,从而做出相应的调整。且其调整过程较为麻烦,每次都需要判断其左右两棵子AVL树的深度情况。相对于红黑树,其将关注点从AVL树的左右两棵子树的深度的失衡情况(也就是平衡因子)转变为了树的节点的颜色。从原先的由于AVL树的深度不一导致的失衡而对该二叉树进行调整转变为了由于该二叉树的相关节点的颜色不符合规则,而对该二叉树进行相应的调整的情况。

红黑树的相关规则:

  1. 每个节点要么是黑色,要么是红色
  2. 根节点是黑色的
  3. 每个叶节点(NULL或空节点)是黑色
  4. 每个红色节点的两个叶子节点都是黑色的(也就是说并不存在两个连续的红色节点)
  5. 从任意一个节点到其子树中的所有路径都包含相同数目的黑色节点

如下图所示:

红黑树1

通过这五条性质,可以通过数学证明来证明,满足这五条性质的二叉树可以将查找和删除操作维持在对数时间内。当我们插入和删除操作时,所做的一切操作都是为了调整树使之符合这五条性质。以下介绍调整树的相关结构的两个基本操作:

  1. 左旋:

左旋动图

  1. 右旋:

右旋动图

旋转的目的是将节点多的一支出让节点给另一个节点少的一支

在讲解相关的操作之前,明确下各个节点的叫法:

各节点名称

以下讨论红黑树的两个基本操作:

1. 插入:

  对于插入操作,我们插入的节点均将其着色为红色,如果插入的节点为黑色节点,那就违背了性质五,需要进行大规模的调整,如果我们插入的是红色节点,那就在插入节点的父节点也是也是红色的时候违反性质四或者是当插入的节点是根节点时,违反性质二。相对而言,其调整程度小于插入节点为黑色节点的情况。需要注意的是红黑树的插入过程与二叉搜索树的相同,只是之后再进行相应的调整。

下面是可能遇到的插入的几种情况:

  1. 当插入的节点为根节点的时候,只需要直接将该节点涂黑即可。

  2. 当要插入的节点的父节点为黑色的时候,这时插入一个红色的节点并没有对着五个性质产生破坏。所以直接插入不用进行调整。

  3. 如果插入的节点的父节点是红色节点,这时就需要分情况进行相应的调整操作,以保证红黑树的相关性质

    1. 插入的节点的父节点为红色节点,且其父节点是祖父节点的左分支的情况:
      这时,也需要分两种情况进行讨论:

      1. 叔叔节点为红色节点,如下情况所示:

      叔叔节点为红色

      这时,只需要将父节点和叔叔节点涂成黑色,将祖父节点涂成红色即可。

      1. 叔叔节点为黑色节点

        当叔叔节点为黑色节点的时候,也分两种情况:

        1. 插入节点是父节点的左分支,如下情况所示:

        插入节点为左分支

        这时,违背了性质四,我们需要对其进行相应的调整,使满足红黑树的相关性质。我们可以通通过对其祖父节点进行右旋同时将祖父节点和父节点的颜色进行互换,这样就变成了:

        插入节点为左分支后

        经过调整之后的红黑树可以符合性质四并且不对其它性质产生破坏

        1. 插入节点为父节点的右分支,如下情况所示:

        插入节点为右分支
        我们可以先对父节点进行左旋操作,变成如下所示:

        插入节点为右分支后

        如果我们把原先的父节点看做是新的要插入的节点,把原先要插入的节点看做是新的父节点,那就变成了当要插入的节点在父节点的左支的情况,这样就可以按照当要插入的节点在父节点的左分支的情况进行旋转,旋转后变成如下的情况:

        插入节点为右分支后2

    2. 插入的节点的父节点为红色节点,且其父节点是祖父节点的右分支,这种情况与插入的节点的父节点为红色节点,且其父节点为祖父节点的右分支的情况互为镜像。为此,只需要将其左节点和右节点进行互换即可。

2. 删除:

  对于删除操作,其过程类似于普通的二叉搜索树的删除过程,分为以下三种情况:

  1. 当删除的元素为叶节点的时候,直接将其进行删除

  2. 当删除的元素有一个子节点时,可以将子节点直接移动到被删除元素的位置,代替被删除的元素

  3. 被删除节点有两个儿子。那么,先找出它的后继节点;然后把“它的后继节点的内容”复制给“该节点的内容”;之后,删除“它的后继节点”。在这里,后继节点相当于替身,在将后继节点的内容复制给"被删除节点"之后,再将后继节点删除。这样就巧妙的将问题转换为"删除后继节点"的情况了,下面就考虑后继节点。 在"被删除节点"有两个非空子节点的情况下,它的后继节点不可能是双子非空。既然"被删除节点的后继节点"不可能双子都非空,就意味着"该节点的后继节点"要么没有儿子,要么只有一个儿子。若没有儿子,则按"情况1 "进行处理;若只有一个儿子,则按"情况2 "进行处理。如图:

元素删除前

将被删除元素与其右支的最小元素互换,变成如下图所示:

元素互换后

然后再将被删除元素删除:

元素删除

加入颜色之后,被删除元素和后继元素互换只是值得互换,并不互换颜色,这个要注意。以下所讲的被删除元素,均指互换后的被删除元素

下面开始讲一下红黑树删除的规则:

  1. 当被删除元素为红时,对五条性质没有什么影响,直接删除。

  2. 当被删除元素为黑且为根节点时,直接删除。

  3. 当被删除元素为黑,且有一个右子节点为红时,将右子节点涂黑放到被删除元素的位置,如图:

删除节点

其中节点a为替换后的被删除节点

变成:

删除节点后

  1. 当被删除元素为黑,且兄弟节点为黑,兄弟节点两个孩子也为黑,父节点为红,此时,交换兄弟节点与父节点的颜色;NULL元素是指每个叶节点都有两个空的,颜色为黑的NULL元素,需要他的时候就可以把它看成两个黑元素,不需要的时候可以忽视他。
    如图:

兄弟节点为黑的删除

变成:

兄弟节点为黑的删除后

5.当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的右支为红色,这个时候需要交换兄弟与父亲的颜色,并把父亲涂黑、兄弟的右支涂黑,并以父节点为中心左转。如图:
由:

兄弟节点为黑色的

变成:

兄弟节点为黑色的后

6.当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的左支为红色,这个时候需要先把兄弟与兄弟的左子节点颜色互换,进行右转,然后就变成了规则5一样了,在按照规则5进行旋转。如图:

兄弟为黑并左旋

先兄弟与兄弟的左子节点颜色互换,进行右转,变成:

兄弟为黑并左旋后

然后在按照规则5进行旋转,变成:

兄弟为黑并左旋后左旋

7.当被删除元素为黑且为父元素的右支时,跟情况5.情况6 互为镜像。

8.被删除元素为黑且兄弟节点为黑,兄弟节点的孩子为黑,父亲为黑,这个时候需要将兄弟节点变为红,再把父亲看做那个被删除的元素(只是看做,实际上不删除),看看父亲符合哪一条删除规则,进行处理变化如图:
由:

全黑情况

变成:

全黑之后

9.当被删除的元素为黑,且为父元素的左支,兄弟节点为红色的时候,需要交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋,就变成了情况4,在按照情况四进行操作即可,变化如下:
由:

兄弟节点为红,父节点为黑

交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋 变成:

兄弟节点为红,父节点为黑后

在按照情况四进行操作,变成:

兄弟节点为红,父节点为黑后换色

博文参考自:最容易懂得红黑树

posted @ 2018-06-05 08:47  林学徒  阅读(355)  评论(0编辑  收藏  举报