引言
我想本篇文章红黑树的故事应该从一个实际的应用讲起。如果我们选择用AVL树来存储数据,会有几个缺点:
首先AVL树的条件太过于苛刻,平衡系数如果大于2,那么我们就需要进行调整,也就是说,如果运气不是很好,我们只要插入两个数,我们就需要调整一次二叉树,很浪费时间。所以我们想要放宽这个条件。放宽这个条件有两个做法,一个是把平衡系数调大,一个是让这个树变成完全二叉树,尽量不去调整二叉树,每个结点可以存放多个数据。
而方法二就是我们的B树。什么是B树,就是一个结点可以存放多个数据,如图:
而我们的红黑树,就是把B树变成二叉树,而这里我们只变化2-3树和2-3-4树。
什么是2-3树,什么是2-3-4树?
拿2-3-4树举例子:
一棵树里面结点有三种类型
1、结点的度为2,可以存储1个数据
2、结点的度为3,可以存储2个数据
3、结点的度为4,可以存储3个数据
因为如果结构太复杂了,2-3-4-5-6。。。那样子也不好变化,所以我们的红黑树只包含2-3树和2-3-4树。
红黑树
红黑树的本质就是B树,它要把B树变成二叉树,所以要把数据不断的往下拆开。但是为什么我们需要分颜色,其实就是因为如果我们要还原成B树,我们需要直到我们那些结点是原来的结点,那些结点是被拆分开的,而原来的结点是黑色,被拆分的结点是红色的。

所以我们对于红黑树,我们可以得到一些性质,这些性质也十分重要:
1、因为根节点不可能是被拆分开的,所以根节点一定是黑色的
2、我们在红黑树里面,把叶子节点叫做失败结点,也就是nullptr结点,可能和我们之前学的结点的意义有些不一样,而红黑树里面的叶子节点一定是黑色的。
3、我们红颜色的来源是由黑节点拆分开的,所以红节点不可能和红节点在一起,因为如果红节点和红节点待在了一起,那下面哪个红节点是由谁拆分开的呢?如果是由上面那一层,那么那一层就应该是黑色的。但是黑色和黑色可以呆在一起,这也比较好理解,没有拆分数据嘛~~
4、一个结点到所有叶子结点的所经历的黑节点数量都相同。红黑树的本质就是B树,而B树的本质是完全二叉树,我们拆开完全二叉树的时候,是不断的往下增加红色的结点,不会有任何黑色结点的增加,所以自然而然,经过的黑色结点数量一样。
5、满足二叉排序树的顺序性。
所以说了半天,其实大家也发现了,红色结点的出现根本不影响黑色结点的本来性质,因为红色节点就是由黑色结点拆分出来的,而标记颜色也仅仅只是为了更方便合并回去。
6、结点的黑高(bh):从某个结点出发,到叶子结点经过的黑色结点(起点不算)
这个概念很容易和树高搞混,因为树的高度是不计算nullptr这个结点的,但是要计算起点,也就是根节点。
所以整个红黑树的黑高就是B树的树高。因为红色结点就是拆分出来的,根本不影响B树本身的性质。
7、那红黑树也有它自己的平衡性。
最长的黑高不可以超过最短的黑高的两倍。理解也非常的简单,假设一个B树一边是一个不拆分,也就是这个路径上根本没有红色节点的出现,而另一边全部拆开,得到红色的结点数量和黑色结点的数量相同
8、红黑树的高度也有所限制,一下是推到过程

总结(红黑树的应用)
Linux的CPU调度算法(完全公平算法)
Linux的epoll多路复用
这主要是因为红黑树对于平衡树的限制条件放宽了,所以可以减少调整的次数,来满足对于更多数据的存储。
本篇文章主要是对于红黑树的性质做了一个陈述,而对于红黑树的代码,会在之后的文章中慢慢呈现出来