数据结构——红黑树

文章目录

    • 1 引言
    • 2 定义
      • 定义节点名称:
    • 3 性质
    • 4 2-3-4树和红黑树的等价关系
    • 5 查找
    • 6 插入
      • 6.1(情景3) 插入节点的父节点为黑色
      • 6.2(情景4) 插入节点的父节点为红色,叔叔节点为黑色
        • 6.2.1(情景4.2.1) 父节点P为G左孩子,插入位置为左孩子
        • 6.2.2(情景4.2.2) 父节点P为G左孩子,插入位置为右孩子
        • 6.2.3(情景4.3.1) 父节点P为G右孩子,插入位置为右孩子
        • 6.2.4(情景4.3.2) 父节点P为G右孩子,插入位置为左孩子
      • 6.3(情景4.1) 插入节点的父节点为红色,叔叔节点为红色
        • 6.3.1(情景4.1) 插入位置为左子树
        • 6.3.2(情景4.1) 插入位置为右子树
    • 7 删除
      • 删除情景1:替换结点是红色结点
        • 7.1 删除红色叶子节点
        • 7.2 删除红色节点,只有左子树或只有右子树
        • 7.3 删除红色节点,既有左子树又有右子树
        • 7.4 删除的黑色节点仅有左子树或者仅有右子树
        • 7.5 删除黑色的叶子节点
    • 8 总结
    • 9 思考题和习题答案
      • 思考题1:黑结点可以同时包含一个红子结点和一个黑子结点吗?
      • 习题1:请画出图15的插入自平衡处理过程。
      • 习题2:请画出图29的删除自平衡处理过程。
    • 推荐阅读

1 引言

红黑树数据结构中最为重要的一种。Java的容器TreeSetTreeMap均使用红黑树实现。JDK1.8HashMap中也加入了红黑树C++ STL中的mapset同样使用红黑树实现。之前的文章已经详细介绍了2-3-4树的性质与操作。本篇文章将从2-3-4树红黑树关系出发,详细阐明红黑树
  2-3-4树红黑树完全等价的,但是2-3-4树的编程实现相对复杂,所以一般是通过实现红黑树来实现替代2-3-4树,而红黑树也同样保证在O(logN)的时间内完成查找插入删除操作。

2 定义

红黑树每个节点都带有颜色属性平衡二叉查找树颜色红色黑色。除了二叉查找树一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

(1)节点是要么红色或要么是黑色
(2)一定是黑色节点
(3)每个叶子节点都带有两个空黑色节点(称之为NIL节点,它又被称为黑哨兵)。
(4)每个红色节点两个子节点都是黑色(或者说从每个叶子所有路径上不能有两个连续红色节点)。
(5)对于任一节点而言,其到叶节点树尾端NIL指针每一条路径都包含相同数目黑节点

从性质5又可以推出:

性质5.1:如果一个结点存在黑子结点,那么该结点肯定有两个子结点
图1就是一颗简单红黑树。其中Nil叶子结点,并且它是黑色的。(值得提醒注意的是,在Java中,叶子结点是为null的结点。)

根据红黑树以上五条定义,我们可以推导出以下几点性质和可能情景:

  • 性质1. 父子节点不可能同时是红节点,即红节点不连续。否则违反定义4
  • 性质2. 如果某节点的一个子节点是黑色,那么该节点必然存在另一个子节点。否则违反定义5
  • 情景1. 一个结点的两个子节点出现一个是红色,一个是黑色的情况是可能出现的
  • 情景2. 父子节点同时是黑色的情况是可能出现的
  • 规律1. 新插入的节点初始化为红色,能最小化变色操作
    现在开始说明红黑树的自平衡。

首先是插入节点的着色。所有关于红黑树自平衡的介绍都说,插入的节点为红色。至于为什么,笔者认为,由于性质3与性质5,任意一结点到每个叶子结点的路径都包含数量相同的黑,且每个叶子节点(NIL)是黑色。新插入的节点初始位置必为替换某个叶子节点,同时自己又会新产生左右两个叶子节点。若新插入的节点为黑,则将会引起从根节点到新节点的路径上黑色节点数量比其它路径多了1。而插入红色节点,则不会有此情况,但是有可能会违反性质4,每个红色结点的两个子结点一定都是黑色,出现连续的两个红色节点,但是不是必然发生。所以新插入的节点为红色,可以使得需要自平衡操作的几率降低。

例如:下图2.1所示的一棵红黑树

数据结构——红黑树_第1张图片

定义节点名称:

数据结构——红黑树_第2张图片
父节点——P(Parent)
祖父节点——G(GrandParent)
叔叔节点——U(Uncle)
当前节点——C(Current)
兄弟节点——B(Brother)
左孩子——L(Left)
右孩子——R(Right)

前面讲到红黑树能自平衡,它靠的是什么?三种操作:左旋、右旋和变色。

  • 左旋:以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。如图3。
  • 右旋:以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。如图4。
  • 变色:结点的颜色由红变黑或由黑变红。

数据结构——红黑树_第3张图片
图3 左旋


数据结构——红黑树_第4张图片图4 右旋


上面所说的旋转结点也即旋转的支点,图4中的P结点。
我们先忽略颜色,可以看到旋转操作不会影响旋转结点的父结点,父结点以上的结构还是保持不变的。
左旋只影响旋转结点和其右子树的结构,把右子树的结点往左子树挪了。
右旋只影响旋转结点和其左子树的结构,把左子树的结点往右子树挪了。

所以旋转操作是局部的。另外可以看出旋转能保持红黑树平衡的一些端详了:当一边子树的结点少了,那么向另外一边子树“借”一些结点;当一边子树的结点多了,那么向另外一边子树“租”一些结点。

但要保持红黑树的性质,结点不能乱挪,还得靠变色了。怎么变?具体情景又不同变法,后面会具体讲到,现在只需要记住红黑树总是通过旋转和变色达到自平衡

<

你可能感兴趣的:(数据结构,数据结构,红黑树,算法)