目录
红黑树的概念:
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色属性,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩 倍,因而是接近平衡的。红黑树需要满足以下特性:
1.每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点
红黑树的插入操作:
步骤:
按照二叉搜索树的方法插入,新插入的节点默认为红色。为什么默认是红色?因为插入红色的节点,只可能违背红黑树的特性三,造成的影响比较小可以调节。如果插入的是黑色的节点,必定会影响特性4,这样整个树的结构可能都需要改变维护的成本会很大。当插入红色节点后,如果其双亲节点的颜色是黑色,没有违反红黑树任何性质,则不 需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连在一起的红色节点,此时需要对红黑树分三种情来讨论。约定:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点。
情况一:
新增节点cur为红色,父节点p也为红色,叔叔节点u为红色。如图所示:
如上图所示插入节点21后,父节点也是红色,所以违反了特性3。这时候应该采用的调整方法是“变色”:将祖父节点的黑色变为红色,父节点和叔叔节点的红色都变为黑色。为什么会这样变化呢?
(1)不可以直接把21变为黑色,因为这样会明显违反特性四。
(2)祖父节点25不一定是整棵树的根节点,途中可能只是一棵树的一部分,所以需要保持这个子树上每条路径黑色节点的数量不变,所以父节点变为黑色的同时,祖父节点变为红色,叔叔节点也变为黑色。(上图中)
(3)上边的操作只是调整的其中一步,因为上述操作将祖父节点g变为了红色,假如祖父节点g的父节点也是红色还需要根据不同的情况继续调整直到上层节点是黑色结束调整,或者g已经是整棵树的根节点将g变为黑色后结束调整。如果25已经是树的根节点了。则将25变为黑色。
情况二:
cur为红,p为红,g为黑,u不存在/u为黑,u不存在和为黑操作相同,所以以u为黑进行讲解,如下图所示:
这时候如果光“变色”已经无法达到目的了,需要改变树的结构然后变色才能达到目的。上图中p是g的左孩子,cur是p的左孩子。我们先对围绕p进行左单旋,设旋转前从跟节点g到任意一个叶子节点的黑节点个数为Original_Bsum 旋转后:
因为c子树黑节点的个数等于d子树或e子树加一,所以设旋转后从根节点p到右子树上的某个叶子节点,黑节点的总数为Right_Bsum == Original_Bsum,但是从p到左子树某个叶子节点黑节点总数left_Bsum == (Origiunal_Bsum - 1)。这时候违反了特性3,需要变色:p变为黑色,g变为红色,如下图所示:
这样变色后Right_Bsum 不变。left_Bsum加一。并且变化后p是黑色,不影响这棵树的其他部分。
情况三:
(1)cur是p的右孩子,p是g的左孩子。
(2)cur是p的左孩子,p是g的右孩子。
这种情况下,改变树的结构需要进行双旋,以(1)为例需要先以p为例左单旋就和情况二相同了,然后再右旋变色完成调整。
红黑树与AVL树的比较:
在查询方面红黑树要略逊于AVL树,因为AVL树比红黑树更加平衡:AVL树任何节点左右子树的高度差最多是1,而红黑树左右子树的高度差是不能超过2倍的关系。但是红黑树非严格的平衡换来了增删节点时旋转次数的降低,而AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多。所以红黑树的插入效率更高。