红黑树

一、红黑树的原理

红黑树和2-3-4树是等价的,由于绝大多数编程语言直接实现2-3-4树会非常繁琐,所以一般是通过实现红黑树来实现替代2-3-4树,而红黑树本也同样保证在O(lgn)的时间内完成查找、插入和删除操作。

红黑树可以看作是一颗节点带颜色的二叉树搜索树。节点只有两种颜色,即红色和黑色。(红黑色只是逻辑颜色,只为区分节点,不带实际意义)

红黑树有如下的特性:

  1. 每个节点不是红色的就是黑色的。
  2. 根节点是黑色的。
  3. 叶子节点是黑色的。
  4. 如果一个节点是红色的,则它的两个儿子都是黑色的。
  5. 对于每个节点,从该节点到其任意叶子节点的路径上的黑色节点数目相同。

上面的性质保证了红黑树的任意路径节点数最大相差不会超过n-1(n为最短路径上的节点数,即该路径上没有红色节点)

对于红黑树的叶子节点,我们一般会设置一个特殊的黑色节点(nil),并将其作为叶子节点或其他空节点。

红黑树的插入和删除节点是发生在叶子节点的父节点上的。

 

如图,上面是一颗红黑树,对于节点“5”、“7”、“9”、“11”,它们都各自有两个”nil“叶子节点。

二、红黑树的平衡

红黑树的平衡是依靠旋转和颜色替换来实现的。

颜色替换为两个节点交换各自的颜色属性。

旋转则为树的左旋和右旋。

红黑树的节点带有指向父节点的指针,因此在左旋、右旋时,一共需要改变六个指向。

如左旋时,x指向父节点和指向右子节点的指向、y指向父节点和指向左子节点的指向、x的父节点指向x的指向、b指向父节点y的指向共6个指向需要相应变化。

左旋、右旋时需要保证x节点和y节点的存在。(一般设计函数会默认这两个节点存在,因此使用者需要自己判断)

 三、红黑树的插入

红黑树在插入节点前,是一颗红黑树。

因此,往红黑树增加一个红色节点,能够最大限度的保证红黑树的性质。

但是,增加节点后,可能会导致该树不符合第4条性质,即红色节点可能插入在红色节点之下,因此在插入后还需要进行树的平衡。

1. 插入操作的实现

第一步,找到合适的插入位置并插入

  根据搜索树的性质找到适合插入的位置,并插入节点

第二步,平衡树

因为当前节点的插入可能导致树的不平衡,将当前节点设置为调整节点,调用调整函数

 

2. 平衡函数原理

平衡函数的一个参数应为插入的当前节点,函数实现如下:

  当前节点的父节点是黑色节点,不需要做任何处理

  当前节点的父节点是红色节点

    当前节点的父节点是祖父节点的左子树

      叔父节点(即祖父节点的右子树)是红色的,

        将父节点和叔父节点变为黑色节点,将祖父节点变为红色节点,将祖父节点设置为调整节点

      叔父节点是黑色的,且父节点是左子节点

        当前节点是父节点的右子节点,将父节点设置为调整节点,父节点左旋   (此目的是为了将调整节点、父节点、祖父节点置换到一条直线上)

        当前节点是父节点的左子节点,将调整节点的父节点置位黑色,将祖父节点置位红色,将祖父节点右旋,调整完成

    当前节点是祖父节点的右子树,(以下操作与上述操作呈镜像)

四、红黑树的删除

红黑树的中序遍历是一个递增序列,我们将在此序列中当前节点的下一相邻节点称为后继节点。

二叉树节点的删除分三种情况

  1. 删除节点是叶子节点,直接删除
  2. 删除节点只有一个子节点,将子节点和父节点链接起来,删除节点
  3. 删除节点有两个子节点,寻找删除节点的后继节点,并用后继节点覆盖删除节点,然后将后继节点作为删除节点

很显然,第三种情况最后也会转换成前两种情况,再进行删除。

1. 删除操作的实现

第一步,找到删除节点

根据二叉树节点的删除我们可以同理找到红黑树的删除节点

第二步,删除节点后平衡树

将节点删除后,树可能变得不平衡,因此我们可能需要平衡树

  删除节点是红色的,树不会变得不平衡,不需要做任何处理

  删除节点是黑色的,树变得不平衡,需要调用平衡函数

2. 平衡函数原理

节点删除后,不平衡的区块可以压缩为删除节点的子树,因此,平衡函数的一个参数应为删除节点的子节点,下面称为调整节点

  调整节点为红色或根节点,将调整节点变为黑色,平衡完成

  调整节点不是根节点且为黑色

    调整节点是左子节点

      调整节点的兄弟节点是红色,将兄弟节点左旋,将兄弟节点设置为黑色,父节点设置为红色,调整节点的兄弟节点发生变化且必定为黑色,进行下述步骤

      调整节点的兄弟节点是黑色

        兄弟节点的子节点(即侄子节点)全为黑色

          将兄弟节点设置为红色,将父节点设置为新的调整节点

        兄弟节点的右子节点(远侄子节点)为红色,左子节点(近侄子节点)颜色任意

          用父节点的颜色覆盖兄弟节点,父节点设置为黑色,父节点左旋,将远侄子节点设置为黑色,调整完成

        远侄子节点为黑色,近侄子节点为红色

          交换兄弟节点和近侄子节点的颜色,兄弟节点右旋,调整节点的兄弟节点发生变化,重新判断

    调整节点是右子节点,(以下操作与上述操作呈镜像)

 

 

五、红黑树的应用

红黑树往往会出现由于树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的情况。在数据较小,可以完全放到内存中时,红黑树的时间复杂度比B树低。

如linux中进程的调度用的是红黑树。定时器的存储数据结构也可以用红黑树实现。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 github:https://github.com/illusorycat/RBtree.git

posted @ 2022-03-01 01:56  幻cat  阅读(88)  评论(0编辑  收藏  举报