Java基础-理解红黑树(插入)

     周围有一些朋友总说:“面试时候看到红黑树真的头大!各类状况太难记了。”确实,若是仅仅想经过记忆来搞定红黑树那确实有点难度的,可是若是理解的话,红黑树其实很简单,因此我就分享一下我对红黑树的理解。面试

1.简单复习下红黑树的规则。

  1. 节点必须是红色或者黑色。
  2. 根节点必须是黑色。
  3. 叶节点(NIL)是黑色的。(NIL节点无数据,是空节点)
  4. 不能出现连续两个红色节点。
  5. 从任一节点出发到其每一个叶子节点的路径,黑色节点的数量是相等的。

2.先讲解一波操做,后面再给出论证

插入操做以下,post

  1. 每次插入第一步,将新插入节点设置为红色。
  2. 每次插入最后一步,将根节点设置为黑色。
  3. 当且仅当新插入节点的父节点为红色时,从新调整红黑树的平衡(调整步骤以下)。
根据插入操做3,只有新插入节点父节点为红色时,才须要调节红黑树,那么父节点为红色时会有几种状况呢?理论上讲只有两种。

第一种:新插入节点 父节点的 兄弟节点 为黑色(左下角节点为新插入节点)3d


第二种:新插入节点 父节点的 兄弟节点 为红色(左下角节点为新插入节点)cdn


两种状况逐个分析。blog

第一种状况下,想要恢复树的平衡,只须要将连续的两个红色节点,分一个给另一个分支便可。这样的话,若是原来的树是平衡的,新树也必然平衡(两个分支的黑色节点数量并未变化)。get


固然说是一回事,作是另外一回事。下面就看看实际状况下,如何操做。it



原树已经有12,10 ,13三个元素,新插入了一个8节点,此时,8与其父节点10都为红色,须要调整。将10设置为黑色,将12设置为红色,而后对节点12进行左旋操做(其实就是把8,10,12这三个顺序节点,从新以中间值10为中心在排一下)。io


若是新插入的节点是11那该怎么办呢。class


此时须要重排的三个节点为12,10,11,可是中间值11在最下面,直接重排不方便。因此须要多一步操做,对10节点进行右旋操做。lazyload


这样12 ,11 ,10 这三个节点也是顺序排列了。下一步操做就同上。若是从右边插入的话,操做也同样,镜像一下就ok。

如今再分析第二种状况(左下角为新插入节点)。


这种状况处理起来更简单,只须要将新插入节点的父节点,以及父节点的兄弟节点一块儿变成黑色,而后将爷爷节点变红便可(两个分支的黑色节点数量依然没有变化)。


由于从爷爷节点往下,每一个分支原来是一个黑色节点,如今依然是一个黑色节点,因此树仍是平衡的,可是须要注意的是,由于爷爷节点由黑变红了。因此还得以爷爷节点为基准,迭代向上判断。直到爷爷节点的父节点为黑色或者爷爷节点为根节点为止。至于迭代中可能的状况,也无非就是咱们列出来的这两种,参照一下便可。

3.最后论证插入操做的合理性:

红黑树规则:

  1. 节点必须是红色或者黑色。
  2. 根节点必须是黑色。
  3. 叶节点(NIL)是黑色的。(NIL节点无数据,是空节点)
  4. 不能出现连续两个红色节点。
  5. 从任一节点出发到其每一个叶子节点的路径,黑色节点的数量是相等的。
插入操做
  1. 每次插入第一步,将新插入节点设置为红色。
  2. 每次插入最后一步,将根节点设置为黑色。
  3. 当且仅当新插入节点的父节点为红色时,从新调整红黑树的平衡


首先,每次插入的第一步将插入节点设置为红色,由于若是树本来是平衡的话,插入一个红色节点并不会影响到规则5(从任一节点出发到其每一个叶子节点的路径,黑色节点的数量是相等的)。

其次,在插入最后一步将根节点设置为黑色,这样规则2(根节点必须是黑色)就永远知足。

最后依据插入操做3(当且仅当新插入节点的父节点为红色时,从新调整红黑树的平衡),以及调整步骤,每次调整事后,均可以保证规则4(不能出现连续两个红色节点)也是能够知足的。

这样一来,只要严格遵循插入的这3条操做,就能够严格的保证红黑树的平衡了。或许你会问刚开始的第一条论证有一个前提条件“树本来是平衡的话”,若是这个前提条件不知足怎么办?

其实当你插入第一个根节点时,树已经处于了平衡的状态。因此只要一开始就遵循插入操做,根本就不会存在树不平衡的状况。因此这个插入操做是合理的。

下一篇:红黑树的删除操做