介绍红黑树之前,我们先来简单了解下二叉查找树(BST)。
首先我们看下二叉查找树的特性:
1.若任意节点的左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值。
2.若任意节点的右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值。
3.左、右子树也分别为二叉排序树。
如上图,这是一颗二叉树,如果我们要查询7,那么只要先跟8比,然后再跟3比,再跟6比,然后找到7,我们可以发现,这正是二分查找的思想,查询二叉树中的一个数据,最大的查询次数就是这颗树的高度。同理,当插入数据的时候,也是从根节点开始依次比较找到位置,再插入。但是二叉树也存在着缺陷,那就是当出现跛脚树的时候,二叉树就会变成了线性查找。举个例子。我们有一个根节点8,如果依次插入7,6,5,4,那么这棵二叉树就会变成下面这个模样:
我去,这还是我认识的树嘛。。。我们发现,树的高度就是元素的个数,查询效率变成了O(n)。为了解决二叉树的平衡问题,下面我们就来引出主角--红黑树(Red–black tree)。
红黑树(英语:Red–black tree)是一种自平衡二叉查找树,是每个节点都带有颜色属性的二叉查找树,颜色为红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
- 节点是红色或黑色。
- 根是黑色。
- 所有叶子都是黑色(叶子是NIL节点)。
- 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)
- 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
下图是一颗红黑树
这5个特性,确保了二叉树的大致平衡:从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。(最长路径为黑和红相间隔,最短路径为全黑节点)
当有插入和删除操作的时候,红黑树的平衡最容易被打破,接下来我们详细分析下各种场景下的破坏,红黑树是如何保持平衡的。
插入
这里先明确一个点,我们把新插入的节点标记为红色(为什么呢?如果设为黑色,就会导致根到叶子的路径上有一条路上,多一个额外的黑节点,这个是很难调整的。但是设为红色节点后,可能会导致出现两个连续红色节点的冲突,那么可以通过1⃣️变色和2⃣️树旋转来调整。)