一、红黑树
特性:1.每个节点是黑色或者红色的
2.根节点是黑色的
3.每个叶节点(NIL)是黑色的
4.不能有相连的红色节点
5.对每个节点,从该节点到其所有叶节点的路径上,均包含相同数量的黑色节点。
红黑树插入:
详细插入:
接上
插入总结:
1.插入红节点(如果黑节点就会出现链表情况,不违反红黑树的特性)
2.待插入节点z与父节点p冲突。
2.1 叔节点u为红色。则需将爷爷节点pp变红,p和u变红。且将pp标记为新的z
2.2 u为黑色。则需要旋转(以z的父节点为轴旋转)。并将父节点p标记为新的z
3.一次以p的旋转必然伴随着一次以pp的旋转。(当z与p与pp同一条线即同一侧,则直接以pp旋转一次即可)
4.循环的修复红黑树的特性,目标是修复到z.p.color为黑色的时候退出循环
红黑树删除(比较复杂,引入算法导论中伪代码与图形):
1.位置替换伪代码:
/**
* 只是处理了u.p的指针指向。在外部还需手动处理v的子类指针
**/
RB-TRANSPLANT(T, u, v) {
if(u.p == T.nil) {
T.root = v
}
else if (u == u.p.left) {
u.p.left = v
}
else
u.p.right = v
v.p = u.p
}
2. 删除伪代码:
RB-DELETE(T, z) {
y = z
y-original-color = y.color
if (z.left == T.nil) {
x = z.right
RB-TRANSPLANT(T, z, z.right)
} else if (z.right == T.nil) {
x = z.left
RB-TRANSPLANT(T, z, z.left);
} else {
y = TREE-MINIMUM(z.right) // z的后继节点
y-original-color = y.color
x = y.right
if (y.p == z) { // y为z的右子节点,且是后继节点
x.p = y
// z被y替换时。y的右节点不需要处理。左节点需要自处理
}
else {
RB-TRANSPLANT(T, y, y.right)
// 为z被y替换处理,子节点需要自处理。左右节点都需要处理
y.right = z.right
y.right.p = y
}
RB-TRANSPLANT(T, z, y)
// z被y替换之后,子节点的自处理。此处只需要处理左节点
y.left = z.left
y.left.p = y
y.color = z.color // 将y置为z的color.最终影响树性质的,决定权在y的原始颜色,y-original-color
}
// z只存在一个子节点的时候。y==z。y == z.color.影响树的性质,依然由y-original-color控制
if (y-original-color == BLACK) {
RB-DELETE-FIXUP(T, x)
}
}
3.删除-红黑树性质修复伪代码:
y的原始颜色y-original-color==RED时。
1.黑高不会变换。
2.y一定不是根节点,所以根节点依然是黑色
3.y只存在一个子节点的时候,y == z 。z被y的唯一子节点代替,无任何改变红黑树性质的可能。
4.y存在两个子节点,且y为z的右子节点时,即y也是z的后继节点。后继节点必然为其右子树中最小的,且y不存在左节点了。y为红色则y.right一定为黑色。y.right替换掉y之后红黑树性质也不可能冲突。
y的原始颜色y-original-color==BLACK时。
1.y为根节点,则其子节点替换,根节点就变红色,则违反了性质2。
2.删除之后,x与x.p(删除之前y.p)都为红色。则违反了性质4
3.将包含y的任一子树的黑节点个数都少一。因此y的任何祖先都补满足性质5。针对这一情况,算法导论中的处理方式为:将y的黑色下方到x,x为红色(自身黑属性+下方红),黑色(自身黑属性+下方黑色),x多出来的黑色并不是体现在x的color属性上,而是针对的x节点。包含x的子树中,x共享了一重黑色,或则两重黑色,从而保证了性质5。但是x却违反了性质1。
RB-DELETE-FIXUP:
RB-DELETE-FIXUP(T, x) {
while (x != T.root && x.color == BLACK) {
// x作为左节点
if (x == x.p.left) {
// x的兄弟节点w
w = x.p.right
// 情况1:x的兄弟结点w为红色,x.p.color必然为黑色。
// 为保证红黑树的特性,可以将x.p与w的颜色改变
// 接着以x.p为轴左转,并不会影响特性。就变成情况2,3,4
if (w.color == RED) {
w.color = BLACK
x.p.color = RED
LEFT-ROTATE(T, x.p)
w = x.p.right
}
// 经过情况1的过滤:2,3,4的w必然是为黑色的
// 情况2:w黑色,w的两个子节点都是黑色的
// 将x上移至x.p,则w子树就会随着x多了一层黑,则需将w变红
if (w.left.color == BLACK && w.right.color == BLACK) {
x = x.p // 如果是情况1过来的,则此时x为红黑色,x.color = RED。所以得退出循环,并将x.color = BLACK
w.color = RED
}
// 情况3:w黑色, w左孩子红色,w的有孩子为黑色
// 交换w.left和w的颜色,并以w向右旋转。则特性不会变。并将w置为x.p.right.
// 情况3就变为情况4了
else if (w.right.color == BLACK) {
w.left.color = BLACK
w.color = RED
RIGHT-ROTATE(T, w)
w = x.p.right
}
// 情况4:w黑色,w的右孩子是红色的
// 将x.p、w、w.right的颜色变换,并以x.p为轴向左旋转,即可保证特性,也可顺带去掉x的多一层黑色。
else {
// w与x.p的颜色交换
// 以x.p为轴旋转,则w子树必然少一个黑,所以将w.right置黑。
// 而x所在子树因转来个x.p的黑节点,则多一黑,刚好x的颜色多了黑直接去掉
// x置为root 退出循环。
w.color = x.p.color
x.p.color = BLACK
w.right.color = BLACK
LEFT-ROTATE(T, x.p)
x = T.root
}
}
}
x.color = BLACK
}
4.删除-图形示例:
总结:红黑树删除,需要找到后继节点y(可能为z的右节点,也有可能非右节点的后继)。
1. 红黑树增加维持红黑树的特性是看其叔叔,删除是看其兄弟节点控制x和w的移动变换,以及旋转和相关的变色。
2. 循环的修复红黑树特性,情况2由情况1过来,导致x.color=red只是作为x多了一层额外的黑色,从而退出循环。还有就是目的性的调整到x的兄弟节点为黑色,且w.right=red即情况4,很容易将原x的子树增加1曾黑色且将x置为root退出循环。
二、B树
一个B树结点通常和一个完整磁盘页一样大,并且磁盘页的大小限制了一个B树结点可以含有的孩子的个数。一个典型的磁盘的长度,可能为2^11~2^14字节。
度:每个结点包含的关键字个数有上界和下界。用一个被称为B树的最小度数degree的固定整数t>=2来表示这些界。
a.除了根结点以外的每个结点必须至少有t-1个关键字。因此除了根结点之外的每个内部结点至少有t个孩子。如果树非空,根结点至少有一个关键字。
b.每个结点至多可包含2t-1个关键字。因此一个内部结点至多有2t个孩子。当一个结点恰好有2t-1个关键字,则称该结点是满的full。
t =< 内部结点数 <= 2t
阶:对于一个m阶B树,根结点的子结点个数为1~m,非根结点的子关键字个数为[m/2]-1~m-1。子结点个数为[m/2]~m.因为当前节点满了之后,继续添加关键字。必然分裂成两半也就是[m/2]-1个关键字,[m/2]个子结点。
[m/ 2]=< 内部结点数 <= m
·综上:m = 2d。
1. B数的插入
伪代码就不贴上了
总结:插入是预分裂。确保到任何叶结点可以直接插入。
插入叶结点,未full(关键字数 = 2d - 1)直接插入。当叶子结点full则需要按中间值分裂。并上移中间关键字。插入的过程中如果发现,遍历的过程中,有full的结点,则提前分裂,分裂好之后再接着遍历插入。
2. B树的删除
总结:删除是预合并,或者预向兄弟结点借用。
1. 被删除节点x的关键字必须满足(t~2t-1).满足条件的叶结点直接删除。
2. x为内部结点,且满足至少t个关键字。则需找k的前驱prev或者后继suc。
ab.如果prev和suc至少有一个满足至少t个关键字,则找到k的前驱k1或者后继(递归下去)。使用k1代替k。
c.prev和suc都不满足至少一个关键字t,皆是t-1个下限关键字。则将k下移至prev且将suc合并至prev并将suc中的孩子指针移动到prev。
3. 从根节点遍历下移的过程中,遇到t-1个的关键字x。
a.找到x的相邻的两个兄弟结点,如果有满足至少t个关键字的b结点。则将b中的关键字上移至父节点(注意递归),并将父节点中的关键字下移至x。并将b中的孩子子指针移入x。
b.找不到满足条件的兄弟结点,则将父节点关键字下移,且将兄弟结点b合并到x。且
b的孩子指针移入x。
三.234树
234树为度数为2的B树。也可与红黑树相互转换.