文章插图
图5 二叉树查找流程图
非常简单,但简单不代表它效率不好 。正由于红黑树总保持黑色完美平衡,所以它的查找最坏时间复杂度为O(2lgN),也即整颗树刚好红黑相隔的时候 。能有这么好的查找效率得益于红黑树自平衡的特性,而这背后的付出,红黑树的插入操作功不可没~
三、红黑树插入
插入操作包括两部分工作:一查找插入的位置;二插入后自平衡 。查找插入的父结点很简单,跟查找操作区别不大:
- 从根结点开始查找;
- 若根结点为空,那么插入结点作为根结点,结束 。
- 若根结点不为空,那么把根结点作为当前结点;
- 若当前结点为null,返回当前结点的父结点,结束 。
- 若当前结点key等于查找key,那么该key所在结点就是插入结点,更新结点的值,结束 。
- 若当前结点key大于查找key,把当前结点的左子结点设置为当前结点,重复步骤4;
- 若当前结点key小于查找key,把当前结点的右子结点设置为当前结点,重复步骤4;
文章插图
图6 红黑树插入位置查找
ok,插入位置已经找到,把插入结点放到正确的位置就可以啦,但插入结点是应该是什么颜色呢?答案是红色 。理由很简单,红色在父结点(如果存在)为黑色结点时,红黑树的黑色平衡没被破坏,不需要做自平衡操作 。但如果插入结点是黑色,那么插入位置所在的子树黑色结点总是多1,必须做自平衡 。
所有插入情景如图7所示:
文章插图
图7 红黑树插入情景
嗯,插入情景很多呢,8种插入情景!但情景1、2和3的处理很简单,而情景4.2和情景4.3只是方向反转而已,懂得了一种情景就能推出另外一种情景,所以总体来看,并不复杂,后续我们将一个一个情景来看,把它彻底搞懂 。
另外,根据二叉树的性质,除了情景2,所有插入操作都是在叶子结点进行的 。这点应该不难理解,因为查找插入位置时,我们就是在找子结点为空的父结点的 。
在开始每个情景的讲解前,我们还是先来约定下,如图8所示:
文章插图
图8 插入操作结点的叫法约定
图8的字母并不代表结点Key的大小 。I表示插入结点,P表示插入结点的父结点,S表示插入结点的叔叔结点,PP表示插入结点的祖父结点 。
好了,下面让我们一个一个来分析每个插入的情景以其处理 。
插入情景1:红黑树为空树最简单的一种情景,直接把插入结点作为根结点就行,但注意,根据红黑树性质2:根节点是黑色 。还需要把插入结点设为黑色 。
处理:把插入结点作为根结点,并把结点设置为黑色 。
插入情景2:插入结点的Key已存在插入结点的Key已存在,既然红黑树总保持平衡,在插入前红黑树已经是平衡的,那么把插入结点设置为将要替代结点的颜色,再把结点的值更新就完成插入 。
处理:
- 把I设为当前结点的颜色
- 更新当前结点的值为插入结点的值
处理:直接插入 。
插入情景4:插入结点的父结点为红结点再次回想下红黑树的性质2:根结点是黑色 。如果插入的父结点为红结点,那么该父结点不可能为根结点,所以插入结点总是存在祖父结点 。这点很重要,因为后续的旋转操作肯定需要祖父结点的参与 。
情景4又分为很多子情景,下面将进入重点部分,各位看官请留神了 。
插入情景4.1:叔叔结点存在并且为红结点
从红黑树性质4可以,祖父结点肯定为黑结点,因为不可以同时存在两个相连的红结点 。那么此时该插入子树的红黑层数的情况是:黑红红 。显然最简单的处理方式是把其改为:红黑红 。如图9和图10所示 。
推荐阅读
- 软件为何不能彻底卸载,因为没用对方式,附预防手机卡的办法
- 2 万字详解,彻底讲透 Elasticsearch
- 我在理解中成长 以理解为话题的作文
- 衣服太透怎么办?简单几招解决白色衣服透明小妙招透底彻底说拜拜
- 中国最好的茶是什么茶,中国六大类茶理解
- 我从来不理解JavaScript闭包,直到有人这样向我解释它
- 中国茶有几种,中国六大类茶理解
- 什么是茶德,中国六大类茶理解
- 化妆|30+女孩:彻底摊牌,我不“装”了
- 一个妙招,5分钟彻底清洗油烟机滤网油泥,双手全程不沾油