红黑树(二)----插入的情况

红黑颜色规则

  1. 节点不是黑色,就是红色(非黑即红);
  2. 根节点一定为黑色;
  3. 叶子节点为黑色是NULL节点,且颜色为黑色;
  4. 根到叶子的所有路径,不可能存在两个连续的红色节点,也就是说如果一个节点为红色,则其两个子节点必须是黑色;
  5. 每个节点到叶子节点的所有路径,都包含相同数目的黑色节点(相同的黑色高度)

红黑树插入

如果插入的是有序数据,那么红黑树的查询效率就比二叉搜索树高,因为此时二叉搜索树不是平衡树,它的时间复杂度O(N)。

新加入的节点为红色节点

从规则5中知道,当前红黑树中从根节点到每个叶子节点的黑色节点数量是一样的,此时假如新插入的是黑色节点的话,必然破坏规则(它所在的路径上会多出一个黑色节点);
但加入红色节点却不一定,除非其父节点就是红色节点才会破坏规则,因此加入红色节点,破坏规则的可能性小一些,所以新加入的节点先为红色。
在这里插入图片描述

插入步骤:

  • 根据二叉搜索树的特性,找到新的节点合适的插入位置;
  • 判断将它作为左孩子还是右孩子;
  • 把它标记为红色节点,如果破坏了原红黑树的规则,所以需要变色+旋转来进行调整。

情况一:插入不破坏原来的特性

在这里插入图片描述
插入的节点是红色,它的父节点就是黑色,所以即不会出现连续的红色节点也不会破坏路径上原有的黑色节点数目,所以它不用改变。

情况二:插入之后只需要变色,不需要旋转

在这里插入图片描述

  • 插入13出现了连续的红色节点,这时候我们先把12改为黑色;
    在这里插入图片描述
  • 这时不满足第5点(每个节点到叶子节点的所有路径,都包含相同数目的黑色节点(相同的黑色高度)),将10改为红色;
    在这里插入图片描述
  • 出现了连续的红色节点5和10,这时候我们先把5和15改为黑色;
    在这里插入图片描述
  • 这时不满足第5点(每个节点到叶子节点的所有路径,都包含相同数目的黑色节点(相同的黑色高度)),25-35-32-NULL经过的黑色节点要小于25-35-32-33-NULL,将35改为黑色;
    在这里插入图片描述
规律:

情况二的核心点在于它爸爸和它叔叔在一个层次上,而且都是红色,能够一起变色,只要插入的或者变色以后破坏了红黑树的什么规则,就对其父节点,叔叔节点等一步一步作出改变。

情况三:既要变色、又要旋转

情况二的核心点在于它爸爸和它叔叔在一个层次上,而且都是红色,能够一起变色,那只要不能一起变色,就需要旋转。关于左旋右旋,这篇博客里面把每一种情况都分析的很到位。

新插入的结点的父亲结点为红色,其叔叔结点为黑色,
  1. 父亲结点为爷爷结点的左孩子,新插入结点为父节点的左孩子(左左情况)
  2. 父亲结点为爷爷结点的右孩子,新插入结点为父结点的右孩子(右右情况)
    上述两种情况都是同一个处理办法:
    比如下图,新插入结点为25,其父亲结点30为红色,其叔叔结点为空黑色叶子结点,且新插入结点和其父节点都是左孩子:
    在这里插入图片描述
  • 将其父亲结点和爷爷结点颜色互换,也就是把30变成黑色,50变成红色,然后针对爷爷结点50进行一次右旋,右旋示意图如下:
    在这里插入图片描述
    来源:右单旋
    在这里插入图片描述
  • 满足要求!注意:旋转并没有改变结点颜色,而改变的是结点的位置,而这位置改变刚好能使得树满足红黑树的第5条性质!
新插入的结点的父亲结点是红色,其叔叔结点是黑色
  1. 插入结点是右结点,父节点是左结点
  2. 插入结点是左结点,父亲结点是右结点

上述两种情况都是同一个处理办法
比如下图,新插入结点是126,其父结点125为红色,其叔叔结点为空的黑色结点,而且插入结点是右结点,父结点是左结点:
在这里插入图片描述
我们将父亲结点125看作当前结点进行左旋,左旋转示意图如下:
在这里插入图片描述
来源:左单旋

  • 旋转结果如下:
    在这里插入图片描述
    现在我们的当前结点是125,现在125的处境和上面的情况是一样的(父节点为红,叔叔结点为黑,插入结点为左结点,父亲结点也为左孩子)现在我们继续按照情况4的处理办法处理上述情况(措施和上面的情况一样,父亲结点126和爷爷130结点互换颜色,然后针对爷爷130结点进行右旋),处理后情况如下:
    在这里插入图片描述
  • 满足要求!

插入结点的几种情况

  1. 树为空,插入的结点为根结点:直接将插入的结点变成黑色

  2. 父亲结点为黑色结点:不需要任何操作

  3. 父亲结点为红色结点的情况下:

    3.1 叔叔结点也为红色结点

    将叔叔和父亲结点改为黑色,爷爷结点改为红色,未完,然后又将爷爷结点当作插入结点看待,一直进行上面的操作,直到当前结点为根结点,然后将根结点变成黑色

    3.2 叔叔结点为黑色结点的情况下:

    • 3.2.1(父亲结点为左孩子,插入结点也为左孩子)||(父亲结点为右孩子,插入结点也为右孩子)将父亲结点和爷爷结点的颜色互换,然后针对爷爷结点进行一次右旋

    • 3.2.2(父亲结点为左孩子,插入结点为右孩子)||(父亲结点为右孩子,插入结点为左孩子) 针对父结点进行左旋,此时左旋后的情况必定是3.2.1的情况,然后按照3.2.1的情况处理

插入结点面临的几种情况

1.爷爷结点为红色结点的情况下,父亲结点只能为黑色(红黑树的性质4),处理操作:上面情况2

2.爷爷结点为黑色的情况下,父亲结点和叔叔结点:可以为红色,也可以为黑色

2.1 父亲结点为黑,叔叔结点为黑:处理操作:上面情况2

2.2 父亲结点为黑,叔叔结点为红:处理操作:上面情况2

2.3 父亲结点为红,叔叔结点为红:处理操作:上面情况3.1

2.4 父亲结点为红,叔叔结点为黑:

 2.4.1 父亲结点为左孩子,叔叔结点为左孩子:处理操作:上面情况3.2.1

 2.4.2 父亲结点为右孩子,叔叔结点为右孩子:处理操作:上面情况3.2.1

 2.4.3 父亲结点为左孩子,插入结点为右孩子:处理操作:上面情况3.2.2

 2.4.4 父亲结点为右孩子,插入结点为左孩子:处理操作:上面情况3.2.2
  • 左左/右右需要进行一次旋转,左右/右左需要进行两次旋转。
  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值