红黑树

博客参考B站视频:https://www.bilibili.com/video/BV1UJ411J7CU?p=2

在学习红黑树前需要先熟悉二叉搜索树的相关知识:https://www.cnblogs.com/lyw-hunnu/p/12606708.html

一、红黑树的性质

  

  (1)性质1:每个节点要么是黑色,要么是红色

  (2)性质2:根结点是黑色

  (3)性质3:每个叶子节点(NIL)是黑色

    NIL 其实就是空节点。

  (4)性质4:每个红色节点的两个节点一定都是黑色,不能有两个红色节点相连。

  (5)性质5:任意一节点到叶子节点的路径都包含数量相同黑节点,俗称 黑高

    例如:对于 F节点来说,它到每一个叶子节点的路径都包含 2个 黑节点。

         对于 P 节点来说,它到每一个叶子节点的路径都包含 3个 黑节点

    从性质 5 可以推出

    性质 5.1:如果一个节点存在黑子节点,那么该节点肯定存在有两个子节点。

    解释:例如 根结点 P ,它有一个黑节点 V ,如果它只有一个节点,也就是说没有 子节点 ,那么结构就会变为:

    

     可见,节点P 左边的 黑高 为 2,而右边的为 3,这就不符合性质 5 了。

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

  1. 变色:节点的颜色由红变黑或由黑变红

  2.左旋:以某个节点为支点(旋转节点),其右子节点变为旋转节点的父节点,右子节点的左子节点变为旋转节点的右子节点,左子节点保持不变。(图都不是我的)

  

  

   3. 右旋:以某个节点为支点(旋转节点),其左子节点变为旋转节点的父节点,左子节点的右子节点变为旋转节点的左子节点,右子节点保持不变。(图都不是我的)

   

  

三、红黑树查找

  

   和二叉搜索树的查找一样,例如查找的数据为 50

  (1)从根结点 80 开始,50 < 80 ,查找 80 的左子树

  (2)当前节点为 40,50 > 40,查找 40 的右子树

  (3)当前节点为 60,50 < 60,查找 60 的左子树

  (4)当前节点为 50,50 == 50 ,查找成功。

  又因为红黑树会自平衡,所以红黑树会保持一个比较平衡的状态,从而保持一个比较良好的查找效率。

三、红黑树的插入

  插入操作包括两部分工作:

  1. 查找插入的位置  2. 插入后自平衡

  注意:插入节点,必须为 红色 ,理由很简单,红色在父节点(如果存在)为黑色节点时,红黑树的平衡没有被破坏,不需要做自平衡

      但如果插入节点为 黑色,那么插入位置所在的子树黑色节点总是多一,必须做自平衡。

  例如有这样一棵红黑树:

  

   1. 插入 值为 20 的节点,则插入结果为:(父节点为黑色)

  

     这个插入结果仍然满足红黑树的五条性质。

  2. 插入值为 75 的节点,则插入结果为:(父节点为红色)

  

    这个插入结果不符合红黑树的 性质4:每个红色节点的两个节点一定都是黑色,不能有两个红色节点相连。

   红黑树插入的场景分析

   下面对插入的一些场景进行分析,在分析之前先进行一些规定

  

   如上图所示,节点 I 为要插入的节点, p 为父亲节点, U 为叔叔节点,PP 为爷爷节点。

   场景1:红黑树为空树

  最简单的一种场景,直接把插入节点作为根节点即可

  注意:根据红黑树性质2,根结点为黑色,因此还需要把该节点设为黑色。

  场景2:插入节点的 key 已存在

  处理:更新当前节点的值,为插入节点的值即可。

  

   情景3:插入节点的父节点为黑色节点。

  因为插入节点是红色的,同时父节点是黑色的,因此不会破坏红黑树的性质。直接插入即可,无需平衡。

  

   情景4:插入节点的父节点为红色节点。

  这类情景下还要分成几种情景:

  情景4-1:有叔叔节点 U。

  因为父亲节点为红色,所以父亲节点一定不是根结点,从而得知一定会有一个爷爷节点,而且爷爷节点为黑色

  爷爷节点--> 父亲节点 --> 插入节点  会以  黑--> --> 进行排序,这种情况下,我们可以将颜色改为 --> 黑 --> 然后将爷爷节点作为插入节点再向上调整

  

   插入情景4-2:叔叔节点不存在或为黑节点,并且插入节点的父节点是爷爷节点的左子节点

  注意:单纯从插入前来看,叔叔节点非红即空(NIL节点),否则会破坏性质5,此途径会比其他途径多一个黑色节点。

      但是叔叔节点为黑节点的这种情况可能会出现再调整过程中。

 

  

  插入情景4-2-1:新插入的节点为父节点的左子节点。(LL双红情况)

   

   处理

    1. 变颜色:将 P 设置为黑色,将 PP 设置为红色

    2. 对 PP 节点进行右旋

 

  

   插入情景4-2-2:新插入的节点为父节点的右子节点。(LR双红情况)

  

   处理:

  1. 左旋 P 节点,得到 LL 双红 情况

   2. 处理 LL双红 情况(变色

  3. 处理 LL 双红 情况(右旋

  

   插入情景4-3:叔叔节点不存在或为黑节点,并且父节点是爷爷节点的右子节点。(对应场景 4-2)

  

   插入情景4-3-1:新插入节点为父节点的右子节点(RR 双红)

   

   处理:(与 LL 双红 的处理方法类似)

  1. 变色:PP 由 黑色 变为 红色 ,P 由 红色 变为 黑色

  2. 以 PP 为节点进行 左旋

  

   插入情景4-3-2:新插入节点为父节点的左子节点。(RL 双红)

  

   处理:

  1.右旋 P 节点,使之形成 RR 双红 情景,然后采用 RR 双红的处理方法。

  2. 变色:PP 由 黑色 变为 红色 ,I 由 红色 变为 黑色

  3. 以 PP 为节点进行 左旋

  

   到这里,基本的增、删、改、查 其实已经说明完了,但是你会奇怪,没有删除。这是因为在一颗二叉搜索树上删除节点已经很麻烦了,更不用说在红黑树上删除。

  删除节点只会在该节点做个标记,说明改节点已被删除,但是在物理空间中不会将其删除。

 

  下面是一个例子,用来帮助你更深刻地理解插入的概念(这幅图是我直接粘贴来的,看不清的可以直接去视频听讲解,指路 45:00)

 

posted @ 2020-04-01 15:17  葡萄籽pp  阅读(201)  评论(0编辑  收藏  举报