红黑树RBT的原理分析及实现
RBT定义
上一篇文章讲了 AVL 树是自平衡的二叉搜索树;在 add 和 remove 之后是通过节点的左右子节点高度差来判断调节节点的平衡;红黑树RBT,也是自平衡的二叉搜索树;RBT是通过下列条件来约束节点实现的平衡:
- 根节点是黑色;
- 叶子节点是黑色;
- RBT树的节点颜色只有红,黑色;
- 一条路径上不能出现连续红色;
- 任意节点到叶子节点的所有路径上黑色节点数相同;
RBT的叶子节点
连续红色节点
任意节点到叶子节点的所有路径上黑色节点数相同
这是一颗红黑树,可以观察到任意一个节点到叶子节点的路径上黑色的节点数都是相等的;比如 根节点500到叶子节点的路径一共10条;这10条路径上每一条路径的黑色节点数都是都是3个;再比如 200节点到叶子节点的路径有4条,这4条路径从叶子到200节点的黑色节点都是 2个;RBT的所有节点都遵守这个规则;
RBT在add时遇到颜色冲突及解决办法
这是target节点与其他节点关系的代称,下面描述会用到;
- parent 父节点
- brother 兄弟节点
- grandpa 祖父节点
- uncle 叔父节点或者 parent的兄弟节点
当有新节点加入RBT时,新节点的颜色应该是黑色还是红色呢?如果新节点的颜色是黑色,那么从新节点 -> root 路径上的所有节点都会增加一个黑色节点,而其他路径黑色节点数不变,这必然导致要重新调节红黑树;新节点是红色,红色可能会导致颜色冲突也可能不冲突;因此新节点颜色是红色;
上面提到新加入RBT的节点颜色是红色,这样可能造成与其parent节点颜色冲突:连续红色。在这种情况就违反了红黑树的定义,需要调整。那问题是如何调整节点颜色呢?在调整颜色的同时必须要兼顾最后一条性质;那直接将parent节点或者自身的颜色改为黑色来解决冲突就不行了;
上图可以看到,这样直接修改节点颜色虽然是可以解决颜色冲突的问题。但是这样改,又引入了新的问题;我们可以直接看 200 节点,200节点有5条路径到叶子节点,经过200节点左分支的2条路径黑色节点是2个,经过200右分支的3条路径黑色节点是3个;不符合定义的最后一条;
直接修改是不行的,那如何修改呢?这需要一些技巧与AVL树一样,需要通过旋转节点,然后再对节点染色;不过与AVL树不一样的是,RBT在旋转之后重新染色还需要考虑uncle节点的颜色;
- uncle节点是黑色的处理;
- uncle是红色的处理
RBT在delete时的颜色调整
在delete时,删除的是红色节点就不会破坏红黑树的定义;如果删除黑色节点,就会破坏最后一条规则了;那如何解决黑色节点被删除的问题呢?经过被删除黑色节点的分支,比不经过该节点的分支少了一个黑色节点。这种情况有2种解决办法:
- 1.通过旋转向兄弟节点或兄弟的子节点借一个红色节点到被删除节点所在分支将其染黑;这样可以使兄弟分支的黑色节点数不变又让被删除分支补充了一个黑色节点,保持黑色节点的平衡;
- 2.如果兄弟节点或者兄弟节点的子节点没有红色节点,就让兄弟节点也减少一个黑色节点(把兄弟节点染红);这样可以保持被删除节点的parent节点左右分支的黑色节点数相等;
- 2.1如果parent是红色,直接将parent染黑,增加一个黑色节点即可达到平衡;
- 2.2如果parent是黑色,grandpa节点就左右失衡了,因此还要继续向上向uncle分支借红色节点;在这个过程中借不到节点就把兄弟变红,直到借到红色节点或者到root节点为止;
图解上面2大类情况,第一种情况分为:兄弟红色向兄弟节点借,兄弟节点的子节点有红色向子节点借;
- 1.1 brother是红色向兄弟节点借一个 节点
- 1.2 brother是黑色,并且有红色的子节点;向兄弟的子节点借一个节点;(PS:这里要注意红色子节点的位置,也是分为 RR,LL,RL ,LR四种类型,不同类型旋转次数不同,下面这个例子是RR 型;后面还会再讲RL)
- 2.1 兄弟及其子节点都是黑色且parent是红色,直接染黑 parent
- 2.2 兄弟及其子节点都是黑色,parent是黑色;继续向上借直到root或者借到节点为止;其实这种情况又回到了前面的几种类型了;
以上就是红黑树对于delete时,删除了黑色节点时的处理方法;总共就2种不同类型的方式:
- 通过旋转增加一个黑色节点;
- 不能增加该分支的黑色节点就将另一个分支也减少一个黑色节点,以此来达到平衡;
上面讲到,在向兄弟子节点借红色节点时要注意红色节点的位置;这个其实跟add操作一样,分四种类型:LL ,LR ,RR ,RL ;其中LL ,RR只需一次旋转;RL ,LR 需要2次旋转;下面以RL为例:
以上是对红黑树add和remove的分析,代码:Gitee-RBT
测试:
@Testpublic void test(){for (int i = 0; i < 10; i++) {addVal(i);}System.out.println("++++++++++++++++add test+++++++++++++++");print();System.out.println("\n++++++++++++++++delete test+++++++++++++++");deleteVal(8);print();}
测试结果可以在网站:test网站 查看结果;
红黑树RBT的原理分析及实现相关推荐
- 红黑树(一)之 原理和算法详细介绍---转帖
目录 1 红黑树的介绍 2 红黑树的应用 3 红黑树的时间复杂度和相关证明 4 红黑树的基本操作(一) 左旋和右旋 5 红黑树的基本操作(二) 添加 6 红黑树的基本操作(三) 删除 作者:Sky W ...
- 红黑树(一)之 原理和算法详细介绍
出处:http://www.cnblogs.com/skywang12345/p/3245399.html 概要 目录 1 红黑树的介绍 2 红黑树的应用 3 红黑树的时间复杂度和相关证明 4 红黑树 ...
- 多线程环境下海量定时任务的定时器设计丨时间轮实现丨红黑树,跳表分析
多线程环境下海量定时任务定时器设计 1. 定时器分析 2. 红黑树,最小堆,跳表实现比较分析 3. 时间轮实现 [Linux后端开发系列]多线程环境下海量定时任务的定时器设计丨时间轮实现丨红黑树,跳表 ...
- 红黑树(一)的原理和算法详细介绍
红黑树的原理和算法的详细介绍 目录 概要 一.R-B Tree简介 二.R-B Tree应用场景及时间复杂度 三.R-B Tree的基本操作(一) 左旋和右旋 1.左旋 2.右旋 四.R-B Tree ...
- 【理论】红黑树的实现原理
红黑树 红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组. 红黑树是在1972年由Rudolf Bayer发明的,当时被称为 ...
- 红黑树RBT基本概念与实现
1. 基本概念 RBT的作用与平衡二叉树类似,目的是优化原始BST查找效率低的问题.RBT需成立,要满足如下条件: 树中每个节点有颜色(红或黑) 根节点必须为黑色 NULL值处称为终端节点,我们可以认 ...
- HashMap之TreeNode(红黑树)源码分析
HashMap-TreeNode源码分析(jdk1.8 HashMap之TreeNode源码分析 属性及构造方法 find() putTreeVal() removeTreeNode() treeif ...
- 算法手札二:红黑树的插入原理,原理与实现篇
红黑树的五大性质(性质四与性质五特别重要) 1. 节点必须是红色或者是黑色 2. 根节点是黑色的 3. 所有的叶子节点是黑色的. 4. 每个红色节点的两个子节点是黑色的,也就是不能存在父子两个节点全是 ...
- HashMap红黑树原理分析
近期学习了 HashMap 实现原理,这篇咱们了解一下红黑树的设计,相比 jdk1.7 的 HashMap 而言,jdk1.8最重要的就是引入了红黑树的设计,当hash表的单一链表长度超过 8 个的时 ...
最新文章
- beego 获取字符串中的数据_MySQL中获取季度、年度等数据
- 平面设计师如何训练自己创意思维
- php特性介绍(贼有用)
- sencha touch 入门系列 (一)sencha touch 简介
- 分析工作试用期收获_免费使用零编码技能探索数据分析
- Chrome 73 DevTools 新功能之 Logpoints
- shell脚本语之运算符
- centos下查看最大Socket连接数
- 从bagging到dropout(deep learning笔记Ian)
- SpringSocial简介
- zoj 2678 Bishops on a Toral Board 同余方程组,完系(3-I)
- 35岁-59岁-人生的二个世界
- 1的阶乘加到20的阶乘
- 红外图像是什么?红外线与计算机视觉相关的研究方向?(Visible and infrared image fusion)
- 考研必备数学公式大全(数学二)(高等数学篇)
- android 去广告浏览器,手机去广告浏览器Adblock Plus Browser
- W dBm功率换算公式
- python图片镜像翻转_OpenCV Python 翻转(镜像)图片 cv.flip
- windows 上面如何解压rar 文件
- JQuery解析二维码
热门文章
- 广州南沙新区规划发布 面积约803平方公里-广州-南沙新区-面积
- c语言中百分号ld是什么意思,URL 中的百分号的麻烦
- 一只刚学java的菜鸡一次练手练习——简易的快递信息管理系统
- 基于SylixOS的中断浅析
- 【石头和爸爸】离家远行前的一个半月
- 滴滴服务分计算机制,滴滴司机,如何避免扣除服务分?服务分到底有多重要?...
- Python之UTC(格林威治时间)转北京时间(本地时间)和获取当前时间
- 计算机网考模拟系统,全国计算机等级考试考网模拟系统
- Linux网络服务之DNS域名解析服务
- fatal: unsafe repository Git权限问题修复