红黑树讲解

定义和规则

定义:红黑树是一种含有红黑节点并能自平衡的二叉查找树,在进行插入和删除等可能会破坏树的平衡的操作时,需要重新自调整达到平衡状态,这里平衡的含义是保证最长路径不超过最短路径的两倍。红黑树是一种非严格平衡的二叉查找树,即不完全符合左右子树的高度差最大为1这个条件

二叉查找树定义:二叉查找树(Binary Search Tree,简称BST)是一棵二叉树,它的左子节点的值比父节点的值要小,右节点的值要比父节点的值大。它的高度决定了它的查找效率

二叉查找树特性:在理想的情况下,二叉查找树增删查改的时间复杂度为O(logN)(其中N为节点数),最坏的情况下为O(N)。当它的高度为logN+1时,我们就说二叉查找树是平衡的

规则:

1、根节点是黑色
2、每个节点非黑即红
3、每个叶子节点(Nil)是黑色
4、每个红色节点的两个子节点一定是黑色(不能有连续的红色节点)
5、任意一节点到每个叶子节点的路径都包含相同数量的黑节点

红黑树示例如下图:

应用:Java 中的 TreeMapJDK 1.8 中的 HashMap 都是基于红黑树结构实现的

特性:插入和删除复杂度都是 O(lgn),且最多旋转三次

优缺点

优点:查询效率高,查询最坏时间复杂度是 O(logn)即整棵树刚好是红黑相隔

缺点:插入删除等操作时需要耗时自调整达到新的平衡状态

为什么要有红黑树?

试想一下,如果二叉树的左右子树高度差相差很大的话,如下图二叉树:

这种二叉树查询起来基本上是线性查询(即需要一层一层的遍历判断查找),比较耗时,为了解决这个问题,引入了具有平衡特性的红黑树

红黑树的三种操作

红黑树进行插入、删除等操作时之所以可以自调整达到平衡状态得益于以下三种操作

1、左旋

以某个节点作为支点(旋转节点),其右子结点变为旋转节点的父节点,右子节点的左子结点变为旋转节点的右子节点,左子节点保持不变。示例如下图:

上述图中,以 P 为旋转节点,P 节点的右节点 V 作为了 P 的父节点,V 节点的左节点 R 作为了 P 的右节点,左子节点 F 保持不变

2、右旋

以某个节点作为支点(旋转节点),其左子节点变为旋转节点的父节点,左子节点的右子结点变为旋转节点的左子节点,右子节点保持不变。示例如下图:

上述图中,以 P 为旋转节点,P 节点的左节点 F 作为了 P 的父节点,F 节点的右节点 K 作为了 P 的左节点,右子节点 V 保持不变

3、变色

节点的颜色由红色变为黑色或者黑色变为红色

红黑树查找

红黑树是一颗平衡二叉树,所以它的查找和平衡二叉树查找是一样的,查找步骤如下:

1、从根节点开始查找,把根节点设置为当前节点

2、如果当前节点为空,直接返回

3、如果当前节点不为空,则用当前节点的 key 和 查找 key 作比较

4、如果当前节点的 key 等于 查找 key,那么返回 该 key 对应的节点

5、如果当前节点的 key 大于 查找 key,则把当前节点的左子节点设置为当前节点,重复步骤 2

6、如果当前节点的 key 小于 查找 key,则把当前节点的右子节点设置为当前节点,重复步骤 2

查找流程图如下:

查找 22 示例如下

红黑树如下:

过程如下图:

红黑树插入

红黑树的插入包含两个步骤:一是查找位置插入节点,二是调整自平衡

一、查找位置插入节点

步骤如下:

1、从根节点开始查找,若根节点为空,那么插入节点作为根节点,结束

2、若根节点不为空,那么把根节点作为当前节点

3、若当前节点为 null,返回当前节点的父节点,结束(没有找到插入节点的位置)

4、若当前节点 key 等于查找 key,那么该 key 所在结点就是插入节点,更新节点的值,结束

5、若当前节点 key 大于查找 key,把当前节点的左子节点设置为当前节点,重复步骤 3

6、若当前节点 key 小于查找 key,把当前节点的右子节点设置为当前节点,重复步骤 3

查找位置插入节点流程图:

这里有个问题就是插入的节点到底是黑色还是红色的呢?

答案是 红色 的,因为如果是黑色的话,肯定打破了红黑树特点5,即任意节点到叶子节点的黑色节点数量将会不相等

二、调整自平衡

红黑树原有节点只有25、15,如下图:

插入13 节点之后,红黑树经过插入、节点变色、自平衡之后成为了新的红黑树,整个过程如下:

 

红黑树删除

红黑树的删除比插入更复杂,包含三个步骤:一是查找位置删除节点(和插入节点步骤一样),二是替代节点替换被删除的节点,三是调整自平衡

一、查找位置删除节点

步骤如下:

1、从根节点开始查找,若根节点为空,结束

2、若根节点不为空,那么把根节点作为当前节点

3、若当前节点为 null,返回当前节点的父节点,结束(没有找到删除的节点)

4、若当前节点 key 等于查找 key,那么该 key 所在结点就是要删除的节点,删除当前节点,结束

5、若当前节点 key 大于查找 key,把当前节点的左子节点设置为当前节点,重复步骤 3

6、若当前节点 key 小于查找 key,把当前节点的右子节点设置为当前节点,重复步骤 3

二、替代节点替换被删除的节点

替代节点替换被删除的节点有以下三种场景:

1、若删除的节点无子节点,则直接删除即可,无需替代节点

2、若删除的节点只有一个子节点,则用其子节点替换被删除的节点

3、若删除的节点有两个节点,则可以使用其后继节点(大于删除节点的右子树最小节点)替换删除节点,或者也可以使用前继节点(小于删除节点的左子树最大节点)替换删除节点

这里说一下怎么样很轻松的找到前继节点和后继节点的方法,脑子中将二叉树的所有节点投射到x坐标上,姑且给这个方法命名为x坐标位置映射法,如下图所示:


例如: P 节点的后继节点就是 R,前继节点就是 M,因此如果删除 P 节点,则使用后继节点 R 替换 P 节点位置或者使用前继节点 M 替换 P 节点位置

三、调整自平衡

下面我们以删除节点25为例,演示一下删除过程,删除25节点之前的红黑树如下图:

这里我们使用前继节点来替换删除节点 25 的位置,根据前面提到的x坐标位置映射法可知  25 的 前继节点是 22,因此删除节点 25的过程如下图所示:

总之,红黑树删除后自平衡的处理可以总结为:

1、自己能搞定的自己处理

2、自己不能搞定的叫兄弟帮忙

3、兄弟都帮忙不了的,通过父母,找远方亲戚帮忙

常见问题

1、红黑树新插入的节点是什么颜色?

红色

原因:插入黑节点必然会影响规则5(所有路径都含有相同数目的黑色节点)这一原则,较难维护

2、根节点为什么是黑色?

性能问题

原因:如果根节点是红色的话,此时增加一个节点(节点必须是黑色,不然打破了规则4)后,则如下图:


此时可以看出,左边黑色节点0个,右边黑色节点1个,该红黑树打破了规则5,即每条路径上的黑色节点数量不一样,那么需要以节点 1 为旋转节点左旋,左旋之后如下图:


从上述图中可以看出,此时该红黑树符合所有规则了。因此如果根节点是红色的话,还需要另外的步骤(旋转)来达到所有规则,这样子肯定耗性能

3、为什么所有的路径上不能有两个连续的红色节点?

为了保证树的平衡,即保证最长路径不超过最短路径的的两倍

原因:通过黑色节点数量来控制树的平衡,最短路径是全是黑色节点,而最长路径则是黑红相隔。由于根节点是黑色的,因此最长路径上应该是黑色和红色节点一样多,而红色节点不能连续则保证了红色节点层数小于等于黑色层数

红黑树和AVL树的比较请参考文章:https://blog.csdn.net/ywlmsm1224811/article/details/97792538

红黑树网页版示例生成链接:https://www.cs.usfca.edu/~galles/visualization/RedBlack.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值