红黑树、B树、234树

本文深入探讨了红黑树的插入与删除操作,详细解析了其保持平衡的策略,包括旋转和颜色调整。同时,介绍了B树的特性、插入与删除过程,强调了B树在保持数据分布平衡上的处理。通过对比,展示了两种数据结构在实际应用中的差异和选择依据。
摘要由CSDN通过智能技术生成

一、红黑树

特性: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树。也可与红黑树相互转换.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值