我们将树中的链接分为两种类型:红链接将两个2-结点连接起来构成一个3-结点,黑链接则是2-3树中的普通链接。确切地说。我们将3-结点表示为由一条左斜的红色链接相连的两个2-结点。
这样的表示法的一个长处是,我们无需改动就能够直接使用标准二叉查找树的get()方法。对于随意的2-3树,仅仅要对结点进行转换。我们都能够马上派生出一颗相应的二叉查找树。
我们将用这样的方式表示2-3树的二叉查找树称为红黑树。
红黑树的还有一种定义是满足下列条件的二叉查找树:
⑴红链接均为左链接。
⑵没有不论什么一个结点同一时候和两条红链接相连。
⑶该树是完美黑色平衡的。即随意空链接到根结点的路径上的黑链接数量同样。
假设我们将一颗红黑树中的红链接画平,那么全部的空链接到根结点的距离都将是同样的。
假设我们将由红链接相连的结点合并,得到的就是一颗2-3树。
相反,假设将一颗2-3树中的3-结点画作由红色左链接相连的两个2-结点,那么不会存在可以和两条红链接相连的结点。且树必定是完美平衡的。
不管我们用何种方式去定义它们,红黑树都既是二叉查找树。也是2-3树。
(2-3树的深度非常小,平衡性好。效率高,可是其有两种不同的结点,实际代码实现比較复杂。而红黑树用红链接表示2-3树中另类的3-结点,统一了树中的结点类型。使代码实现简单化,又不破坏其高效性。
)
颜色表示:
由于每一个结点都仅仅会有一条指向自己的链接(从它的父结点指向它),我们将链接的颜色保存在表示结点的Node数据类型的布尔变量color中(若指向它的链接是红色的,那么该变量为true,黑色则为false)。
当我们提到一个结点颜色时,我们指的是指向该结点的链接的颜色。
旋转
在我们实现的某些操作中可能会出现红色右链接或者两条连续的红链接,但在操作完毕前这些情况都会被小心地旋转并修复。
(我们在这里不讨论旋转的几种情况,把红黑树看做2-3树,自然能够得到正确的旋转后结果)
插入
在插入时我们能够使用旋转操作帮助我们保证2-3树和红黑树之间的一一相应关系,由于旋转操作能够保持红黑树的两个重要性质:有序性和完美平衡性。
热身:
向2-结点中插入新键
(向红黑树中插入操作时,想想2-3树的插入操作。红黑树与2-3树在本质上是同样的,仅仅是它们对3结点的表示不同。
向一个仅仅含有一个2-结点的2-3树中插入新键后,2-结点变为3-结点。
我们再把这个3-结点转化为红结点就可以)
向一颗双键树(即一个3-结点)中插入新键
(向红黑树中插入操作时,想想2-3树的插入操作。你把红黑树当做2-3树来处理插入。一切都变得简单了)
(向2-3树中的一个3-结点插入新键。这个3结点暂时成为4-结点,然后分裂成3个2结点)