红黑树的属性
红黑树是一种特殊的二叉搜索树,除了拥有二叉搜索树的属性外,还附加有以下的属性:
- 每个节点都是红色或者黑色
- 根节点为黑色
- 所有的叶子节点为NIL,且皆为黑色
- 如果一个节点为红色,那么它的子节点皆为黑色
- 对于给定树中的任一节点,它与自身下级所有的叶子节点构成的路径中黑色结点的个数是相同的
对于初初接触到红黑树的人来说,这些属性往往是较难理解的。红色是什么呢,黑色又是什么呢,维护这些属性的意义又是什么呢?这一连串的问号就得从红黑树的起源 —— 2-3-4 树中去寻找答案了。
2-3-4 树
2-3-4 树并不是二叉搜索树, 而是一个阶为4的B树。对于B树不熟悉的同学,可以粗略地理解为二叉搜索树的一种扩展,但是它的每个节点中最多可以含有 m - 1 个数据,而它的子节点最多含有 m 个,其中 m 被称为B树的阶。就拿 2-3-4 树举个例子,那么它的每个节点可能的数据个数为 1个,2个或者3个,而这些节点分别对应的子节点个数最多为2个,3个和4个。这也是 2-3-4 树名名称的由来。下面是一个 2-3-4 树的例子:
图片来源wiki
2-3-4 树的插入
为了更加直观地理解 2-3-4 树,我构造了一个 2-3-4 数的数据插入流程,我将按顺序插入 1,2,3,4,5,6,7,8,9,构成一个 2-3-4 树。
首先是插入1,2,3,4:
image.png
可以看到,此时根节点即为叶子节点,当叶子节点数据不足3个时,新来的数据就会往叶子节点添加数据,而在插入数据4的时候,此节点已经容纳不下了,则会将中间的数据即为2提取出来,作为父节点,1和3作为子节点,然后将4插入。
下面将5和6插入:
image.png
当需要插入6的时候,我们就需要对包含数据3,4,5这一节点进行拆分了,而这一节点是存在父节点的,那么只需要将中间数据4晋升到父节点中,然后3和5作为子节点,再对6进行插入即可。
下面略去7的插入图,看看插入8和9时树的情况:
image.png
这里需要注意的是,在插入数据9的过程中,尽管7,8节点还有位置,我们仍然对2,4,6 节点进行了拆分,原因是插入数据时我们是从上往下进行查找插入位置的,如果此时父级数据达到上限,我们就得提早进行拆分,因为子节点会存在晋升的可能,这样在子节点晋升时,只需简单地把中间数据合并到父节点即可。
这其实就是 Guibas-Sedgewick 发明的自上而下的插入算法。整个算法概括起来就是从上而下遍历,遇到达到上限的节点则将其拆分,最后在叶子节点插入该数据。
从 2-3-4 树到红黑树
从上面的图文中,我们已经粗略地了解了2-3-4树。那么这个树和红黑树又有什么关联呢,以下是维基百科的描述。
2–3–4 trees, however, can be difficult to implement in most programming languages because of the large number of special cases involved in operations on the tree. Red–black trees are simpler to implement, so tend to be used instead.
根据这段描述,我们可以得知,红黑树其实就是为了更方便计算机语言实现 2-3-4 树而创造出来的一种数据结构。也就是说,每棵红黑树都有着一颗2-3-4树与之对应。其基本转换规则如下:
image.png
从这些转换规则可以得知,红黑树红色的节点表示其与父节点在 2-3-4 树中是属于同一节点的数据。根据这一系列规则,我们就能很轻易地去理解红黑树的属性了。
- 每个节点都为红色或黑色:红色代表其与父节点有关联,黑色则代表其于父节点没有关联
- 根节点皆为黑色:根节点没有父节点,即不可能与父节点有关联
- 所有叶子节点为NIL,且皆为黑色:这个我理解为红黑树的定义,此外它与第四条属性成立的前提条件
- 如果一个节点为红色,那么它的子节点皆为黑色:若红色的节点子节点也为红色,则找不到一颗2-3-4树能与之对应了
- 对于给定树中的任一节点,它与自身下级所有的叶子节点构成的路径中黑色结点的个数是相同的:这个就是2-3-4树根据定义转换成红黑树的规律。原因在于红黑树中的黑色节点,要么是 2-3-4 数中的叶子节点,要么是内部结点的中间数据。这其实也是B树的一个定义的另一个体现,即每个非叶子节点含有k个数据,则必定有k+1个子节点。也就是说,2-3-4 树中的任一节点,到叶子节点经历的路径中经过的内部结点个数永远是相等的。
更多更垃圾的博客内容请关注狗带博客, 比心
网友评论