而原本-3节点的左和中节点,转变为了B的左子节点和右子节点。
原书对红黑树的一种等价定义(网上一搜红黑树出来的五个定义,是结论上的定义,这里的定义是从实现角度出发的):
红链接均为左链接;
没有任何一个节点同时和两条红链接相连;
该树是完美黑色平衡的,即任意空链接到根结点的路径上的黑链接数量相同。
对于以上第一条,是一个约定,就像1+1为什么等于2;如果设定红链接都是右链接也没啥关系;
对于第二条,想想把红链接打开的情况:红链接连接的连个节点,在23树中本是平级的存在;如果存在两个连续的红链接,代表有三个节点在同一个级别;这违反了23树的定义;
红黑树既要 保证23树的定义也要保证二叉树的定义。
对于第三条,黑色节点,也就是普通节点,为了保证局部与整体的平衡,需要选装和变色来处理。
关于一二点、在红黑树中需要特别的去维护、如果红链接出现在了右链接,就需要左旋;如果出现了一个节点上有两个红链接,需要变色或是旋转
/
或\
字形,如果两条红链接是这种形状,对其右旋或左旋即可;>
或<
字形,如果是这种形状,需要先对中间层节点旋转;以上强调的是红链接,原书中也是以链接来解释,能更好提现折叠,但是网上很多都上来直接说红节点和黑节点;
至于插入和删除;插入过程会不断出现违反上述 1
,2
性质的过程,需要不断旋转和变色,在AVL的旋转上再加些自身逻辑判断即可;
而删除的话,参考RedBlack.pdf吧……
对于删除的补充概括,删除一个节点,难处理的情况主要有两种:
根据Java的TreeMap的fixAfterDeletion
方法,熟悉23树与红黑树后这里使用红节点的说法,将转换时对应的23树画出来:
以下情况,试待删除节点的左节点为current(当然也可以是右节点,这里先讨论待删除节点的左节点为current的情况),待删除节点的右节点为sibling;在变色和旋转之后,要保证current和sibling一直是兄弟关系——指的是对应23树中的兄弟关系;
对于如何移动current和sibling,就像那种早年的九宫格拼图游戏,有一个空白的,努力利用空白将拼图拼完整;这里就是利用红节点;sibling和current围绕红节点来移动保证平衡
看到上述结构在23树中,C和E是一个3-节点, 只不过在红黑树中,将E节点描绘成了红色,这里先想办法将C转成红色,如果在23树中,其实很简单,只要将C往X上归并,C就可以变成红黑树中的红节点,如图:
在红黑树中,需要如何操作: 将E变为黑色普通节点,C变为红色节点即可。完整对应关系如下:
然后再对current的parent进行左旋,再将sibling移到current父节点的右节点。
在红黑树中只要将sibling染红即可,然后将current移到current的父节点;这里解释一下为啥要将current往他的父节点移动:因为sibling变红了,代表sibling与其父节点在23树中是一个3-节点,是红黑中同级的的存在!所以要将current往他的父节点移动,以保证current和sibling还是兄弟不会乱伦。
虽然对应的红黑树中他们的关系变了,但是无所谓,红黑树只要保证平衡即可
以上是将要删除的节点的左节点视为current,如果将右节点视为current操作与上述的是对称的。 在上述各种情况中,最终需要的形态是4,与RedBlack.pdf的deleteMax情况相似;
局部
deleteMax标准形态,这种情况下删除不会影响整个树的平衡,所以123只是一个过渡,就像拼图过程中的一些技巧。终上所述,delete就像是一个九宫格拼图,红色节点就是那一块空白,如何围绕这个空白,拼好这个拼图,前人都已经总结好了……
你看那个人好像一条狗啊