图解红黑树

图解红黑树

1、红黑树的五条规则

红黑树除了符合二叉搜索树的基本规则外,还添加了如下特性:算法

  • 规则1:节点是红色或黑色的;
  • 规则2:根节点是黑色的;
  • 规则3:每一个叶子节点都是黑色的空节点(NIL节点);
  • 规则4:每一个红色节点的两个子节点都是黑色的(从每一个叶子到根的全部路径上不可能有两个连续的红色节点);
  • 规则5:从任一节点到其每一个叶子节点的全部路径都包含相同数目的黑色节点;

image-20200303121529068

红黑树的相对平衡数据结构

前面5条规则的约束确保了如下红黑树的关键特性:ide

  • 根到叶子节点最长路径,不会超过最短路径两倍
  • 结果就是这棵树基本是平衡的;
  • 虽然没有作到绝对的平衡,可是能够保证在最坏的状况下,该树依然是高效的;

为何能够作到最长路径不超过最短路径的两倍呢?递归

  • 性质4决定了路径上不能有两个相连的红色节点;
  • 因此,最长路径必定是红色节点和黑色节点交替而成的;
  • 因为根节点和叶子节点都是黑色的,最短路径可能都是黑色节点,而且最长路径中必定是黑色节点多于红色节点;
  • 性质5决定了全部路径上都有相同数目的黑色节点;
  • 这就代表了没有路径能多于其余任何路径两倍长。

2、红黑树的三种变换

插入一个新节点时,有可能树再也不平衡,能够经过三种方式的变换使树保持平衡:ip

  • 变色
  • 左旋转
  • 右旋转

2.1.变色

为了从新符合红黑树的规则,须要把红色节点变为黑色,或者把黑色节点变为红色v8

插入的新节点一般都是红色节点get

  • 当插入的节点为红色的时候,大多数状况不违反红黑树的任何规则;效率

  • 插入黑色节点,必然会致使一条路径上多了一个黑色节点,这是很难调整的;
  • 红色节点虽然可能致使红红相连的状况,可是这种状况能够经过颜色调换和旋转来调整;原理

2.2.左旋转

以节点X为根逆时针旋转二叉搜索树,使得父节点原来的位置被本身的右子节点替代,左子节点的位置被父节点替代;数据结构与算法

image-20200303132706061

详解:

如上图所示,左旋转以后:

  • 节点X取代了节点a原来的位置;
  • 节点Y取代了节点X原来的位置;
  • 节点X的左子树 a 仍然是节点X的左子树(这里X的左子树只有一个节点,有多个节点时一样适用,如下同理);
  • 节点Y的右子树 c 仍然是节点Y的右子树
  • 节点Y的左子树 b 向左平移成为了节点X的右子树

除此以外,二叉搜索树左旋转以后仍为二叉搜索树:

image-20200303132617108

2.3.右旋转

以节点X为根顺时针旋转二叉搜索树,使得父节点原来的位置被本身的左子节点替代,右子节点的位置被父节点替代;

image-20200303132529476

详解:

如上图所示,右旋转以后:

  • 节点X取代了节点a原来的位置;
  • 节点Y取代了节点X原来的位置;
  • 节点X的右子树 a 仍然是节点X的右子树(这里X的右子树虽然只有一个节点,可是多个节点时一样适用,如下同理);
  • 节点Y的左子树 b 仍然是节点Y的左子树
  • 节点Y的右子树 c 向右平移成为了节点X的左子树

除此以外,二叉搜索树右旋转以后仍为二叉搜索树:

image-20200303132501369

3、红黑树的插入操做

首先须要明确,在保证知足红黑树5条规则的状况下,新插入的节点必然是红色节点

为了方便说明,规定如下四个节点:新插入节点为N(Node),N的父节点为P(Parent),P的兄弟节点为U(Uncle),U的父节点为G(Grandpa),以下图所示:

image-20200303120344016

3.1.状况1

当插入的新节点N位于树的根上时,没有父节点。

这种状况下,只须要将红色节点变为黑色节点便可知足规则2 。

image-20200303132357511

3.2.状况2

新界点N的父节点P为黑色节点,此时不须要任何变化。

此时既知足规则4也知足规则5。尽管新节点是红色的,可是新节点N有两个黑色节点NIL,因此通向它的路径上黑色节点的个数依然相等,所以知足规则5 。

image-20200303132304098

3.3.状况3

节点P为红色,节点U也为红色,此时节点G必为黑色,即父红叔红祖黑

在这种状况下须要:

  • 先将父节点P变为黑色;
  • 再将叔叔节点U变为黑色;
  • 最后将祖父节点G变为红色;

即变为父黑叔黑祖红,以下图所示:

image-20200303132148128

可能出现的问题:

  • N的祖父节点G的父节点也多是红色,这就违反了规则4,此时能够经过递归调整节点颜色;
  • 当递归调整到根节点时就须要旋转了,以下图节点A和节点B所示,具体状况后面会介绍;

image-20200303132050765

3.4.状况4

节点P是红色节点,节点U是黑色节点,而且节点N为节点P的左子节点,此时节点G必定是黑色节点,即父红叔黑祖黑

在这种状况下须要:

  • 先变色:将父节点P变为黑色,将祖父节点G变为红色;
  • 后旋转:以祖父节点G为根进行右旋转;

image-20200303131956298

3.5.状况5

节点P是红色节点,节点U是黑色节点,而且节点N为节点P的右子节点,此时节点G必定是黑色节点,即父红叔黑祖黑

在这种状况下须要:

  • 先以节点P为根进行左旋转,旋转后如图b所示;
  • 随后将红色节点P黑色节点B当作一个总体的红色节点N1,将新插入的红色节点N当作红色节点P1 如图c所示。此时总体就转换为了状况4。

image-20200303140225631

接着能够按照状况4进行处理:

  • 先变色:将N1节点的父节点P1变为黑色,将祖父节点G变为红色;

  • 后旋转:以祖父节点G为根进行右旋转,旋转后如图 e 所示;
  • 最后将节点N1和P1变换回来,完成节点N的插入,如图 f 所示;

image-20200303131736316

3.6.案例

在二叉树中依次插入节点:10,9,8,7,6,5,4,3,2,1 。

若是直接采用普通的二叉搜索树,节点所有插入后是这样的:

image-20200303161149709

是一个严重的不平衡树,至关于一个链表,不能体现出二叉搜索树的高效率。而按照红黑树的五条规则插入节点就能最大程度保证搜索二叉树是一棵平衡树。如下为过程详解:为了方便解释省略了部分成黑树的叶子节点(NIL)

插入10

符合状况1

  • 插入节点10;
  • 将节点10的颜色变为黑色;

image-20200303161257010

插入9

符合状况2

  • 不须要任何变化;

image-20200303161919072

插入8

快速判断属于状况3仍是状况4的方法:

重新插入的节点N出发,按图示箭头通过的四个节点,若为红红黑红3个红色节点则为状况3,若为红红黑黑两个红色节点则为状况4;

image-20200303162613413

符合状况4

  • 父节点9变成黑,祖父节点10变为红;
  • 以祖父节点为根进行右旋转;

image-20200303163803388

插入7

符合状况3

  • 父节点8和叔节点10变为黑,祖父节点9变为红;
  • 此时会出现问题:不符合规则2,即根节点不为黑,此时能够把以9为根节点的二叉搜索树看成一个总体做为一个新插入的节点N,而此时又符合状况1,只须要把9变回黑色便可。

image-20200303165135028

插入6

符合状况4

  • 父节点7变为黑,祖父节点8变为红;
  • 以祖父节点8为根进行右旋转;

image-20200306170016958

插入5

符合状况3

  • 父节点6和叔节点8变为黑,祖父节点7变为红;

image-20200303170150314

插入4

符合状况4

  • 父节点5变为黑,祖父节点6变为红;
  • 以祖父节点6为根进行右旋转;

image-20200303171028009

插入3

第一次变换:符合状况3

  • 父节点4和叔节点6变为黑,祖父节点5变为红;

变换以后发现5和7为相连的两个红色节点,因而把以5为根的整个子树当作一个新插入的节点N1,再进行第二次变换。

image-20200303171755035

第二次变换:符合状况4

  • 父节点7变为黑,祖父节点9变为红;
  • 以祖父节点9为根进行右旋转;

image-20200303172800302

最后复原N1获得变换后的红黑树:

image-20200303173158141

插入2

符合状况4

  • 父节点3变为黑,祖父节点4变为红;
  • 以祖父节点4为根进行右旋转;

image-20200303174011409

插入1

第一次变换:符合状况3

  • 父节点2和叔节点4变为黑,祖父节点3变为红;

变换以后发现3和5为相连的两个红色节点,因而把以3为根的整个子树当作一个新插入的节点N1,再进行第二次变换。

image-20200303180603741

第二次变换:符合状况3

  • 父节点5和叔节点9变为黑,祖父节点7变为红;即由图 b -> 图 c 。

变换以后发现根节点7为红色不符合规则2,因此把以7为根节点的红黑树当作一个新插入的节点N2,再进行第三次变换。

第三次变换:符合状况1

  • 直接将根节点7变为黑色便可。

image-20200303181133397

由此,完成了1~10节点的插入,虽然没有遇到状况5,不过状况5通过左旋转的操做即可转换为状况4,原理同样。以下图所示,将这棵红黑树的叶子节点NIL补全以后,经检验知足红黑树的五条规则,而且基本属于平衡树,效率较高。

image-20200303182326442

4、红黑树的删除操做

红黑树的删除操做结合了复杂的二叉树的删除操做和复杂的红黑树的插入规则,总体来讲难度很是大,篇幅较长,这里暂不进行探讨。

参考资料:JavaScript数据结构与算法

相关文章
相关标签/搜索