12.红黑树

  邂逅 红黑树

    首先,红黑树很难,难到什么程度呢?

      首先你跟别人聊数据结构的时候,他不会和你聊红黑树,因为它是数据结构中一个难点中的难点

      数据结构的学习本来就比较难了,红黑树是又将难度上升一个档次的知识点

    面试的时候经常出现这个场景:

      面试管:你知道红黑树吗?

      面试者:知道啦

      面试管:知道原理吗?

      面试者:不知道啊

      面试官:那你让“不”过来面试我们公司吧,

          你先回去等通知吧

    哪些面试会出现红黑树呢?

      通常在比较知名的互联网公司面试会出现红黑树的题目

      因为它可以作为你对数据结构掌握深度的很好考虑点

      但是在除去大型互联网公司之外,几乎不会考虑到红黑树

      因为面试管很有可能自己都不懂

    OK,在这里,我们就一起来踏入数据结构红黑树这块禁区

  红黑树的规则

    红黑树,除了符合二叉搜索树的基本规则外,还添加了一下:

      节点是红色或黑色

      根节点是黑色

      每个叶子节点都是黑色的空节点(NIL节点)

      每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个链接的红色节点)

      从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点

    这些规则会让人一头雾水

      完成搞不懂规则叠加起来,怎么让一棵树平衡的

      但是它们还是被一些聪明的人发明出来了

      

 

      到底是怎么平衡的呢?

  红黑树的相对平衡

    前面的约束,确保了红黑树的关键特性:

      从根到叶子的最长可能路径,不能超过最短可能路径的两倍长

      结果就是这个树基本是平衡

      虽然没有做到绝对的平衡,但是可以保证在最坏的情况下,依然是高效的

    为什么可以做到最长路径不超过最短路径的两倍呢?

      性质4决定了路径不能有两个相连的红色节点

      最短的可能路径都是黑色节点

      最长的可能路径是红色和黑色交替

      性质5所有路径都有相同数目的黑色节点

      这就表明了没有路径能多余任何其他路径的两倍长

  变色

    插入一个新节点时,有可能树不再平衡,可以通过三种方式的变换,让树保持平衡

      换色-左旋转-右旋转

    变色:

      为了重新符合红黑树的规则,尝试把红色节点变为黑色,或者把黑色节点变为红色

    首先,需要知道插入的新的节点通常都是红色节点

      因为在插入节点为红色的时候,有可能插入一次是不违反红黑树任何规则的

      而插入黑色节点,必然会导致有一条路径上多了黑色节点,这是很难调整的

      红色节点可能导致出现红红相连的情况,但是这种情况可以通过颜色调换和旋转来调整

      

 

 

 

   旋转

    左旋转

    逆时针旋转红黑树的两个节点,使得父节点被自己右孩子取代,而自己称为自己的左孩子、

    

 

    图中,身为右孩子的Y取代了X的位置,而X变成了Y的左孩子。此为左旋转

    问题:如果它们有子树是否会影响旋转?

    右旋转

    顺时针旋转红黑树的两个节点,使得父节点被自己左孩子取代,而自己称为自己的右孩子

    

 

    图中,身为左孩子的Y取代了X的位置,而X变成了Y的右孩子。

    问题:如果它们右子树是否影响旋转呢?

  插入操作

    接下来,讨论一下插入的情况:

      设要插入的节点为N,其父节点为P

      其祖父节点为G,其父亲的兄弟节点为U(即P和U是同一个节点的子节点)

    情况一:

      新节点N位于树的根上,没有父节点

      这种情况下,我们直接将红色变换成黑色即可,这样满足性质2

    情况二:

      新节点的父节点P是黑色

      性质4没有失效(新节点是红色的),性质5也没有任何问题

      尽管新节点N有两个黑色的叶子节点nil,但是新节点N是红色的,所以通过它的路径中黑色节点的个数依然相同,满足性质5

  情况三:

    情况三:

        

      P为红色,U也是红色

    操作方案:

      将P和U变换为黑色,并且将G变换为红色

      现在新节点N有了一个黑色的父节点P,所以每条路径上黑色节点的数目没有改变

      而从更高的路径上,必须都会经过G节点,所以那些路径的黑色节点数目也是不变的,符合性质5、

    可能出现的问题:

      但是,N的祖父节点G的父节点也可能是红色,这就违反了性质3没可以递归的调整颜色

      但是如果递归调整颜色到了根节点,就需要进行旋转了,待会儿我们的例子中会遇到这个问题

  情况四:

    情况四:

      

      N的叔叔U是黑节点,且N是左孩子

    操作方案:

      对祖父节点G进行依次右旋转

      在旋转查收的树中,以前的父节点P现在是新节点已经以前父节点G的父节点

      交换以前的父节点P和祖父节点G的颜色(P为黑色,G变成红色 - G原来一定是黑色,为什么?)

      B节点向右平移,称为G节点的左子节点

  情况五:

    情况五:

      

      N的叔叔U是黑色节点,且N是右孩子

    操作方案:

      对P节点进行依次左旋转,形成情况四的结果

      对祖父节点G进行一次右旋转,并且改变颜色即可

  红黑树案例

    案例:一次插入10到1

    插入10

      插入节点10

      将节点10的颜色改为黑色

      

    插入9

      符合情况2

      不需要任何变化

      

 

    插入8

      情况4

      

 

    插入7

      符合情况3

      原来:父红叔黑祖黑 -> 父黑叔黑祖红

      问题:不符合规则2

      

 

     插入6

 

 

       情况4

      父变成黑色

      祖父变成红色

      进行右旋转

       

 

     插入5

       符合情况3

      6节点变成黑色

      8节点变成黑色

      7节点变成红色

       

 

    插入4

      情况4

      颜色变换:5节点变成黑色,6节点变成红色

      旋转操作

      

 

    插入3

      第一次变化:符合情况3:4节点变成黑色,6节点变成黑色,5节点变成红色

      第二次变化:符合情况4:7节点变成黑色,9节点变成红色,右旋转

      

 

     插入2

      3节点颜色变成黑色,4节点颜色变成红色

      右旋转

      

 

     插入1

      第一次变化:2和4节点变成黑色,3节点变成红色

      第二次变化:5和9节点变成黑色,7变成红色

      

  删除&代码

    红黑树的删除

      我们已经学习过了二叉搜索树的删除操作,比较复杂

      我们已经学习过了红黑树的插入规则,比较复杂

      红黑树的删除操作呢?

      它就需要将两个复杂的操作结合起来考虑,所以难度非常大

    插入和删除的代码实现:

      插入的步骤我们已经一步步的进行了分析

      分析完成后,写出插入的代码并不是很难

      删除也需要按照插入一样,分成很多种情况,然后写出最终的代码形式

    目前,我们已经讲解了树的很多知识了,作为前端数据结构和算法的补充,就先到这里

      有机会的时候,我们用其他语言来进一步了解红黑树的删除和代码,比如Java 比如python

 

posted @ 2022-04-17 11:31  风太温柔  阅读(99)  评论(0编辑  收藏  举报