zoukankan      html  css  js  c++  java
  • 算法导论笔记 红黑树(1)

    //

    //  RB_tree.cpp

    //  笔记

    //

    //  Created by fam on 15/3/17.

    //

    //




    //RB_tree

    {

        /*

            RB_tree概述:

            RB_tree是一种平衡二叉树,必须满足4个条件:

            1:每个节点不是红色就是黑色

            2:根节点为黑色(叶子节点也为黑色)

            3:如果节点为红,其子节点必须为黑(也就是说不能同时出现两个红色节点)

            4:每个节点 到达叶子节点的 每一条路径 必须拥有同样数量的 黑色节点 (这个数量(不包含自己)称之为黑高)

            

            在平衡RB_tree的时候可以先从上到下进行调整,每次遇到一个节点的子节点都是红色的

            就把这个节点改成红色,把子节点改成黑色。 如果该节点的父节点也是红色,

            就做一次(也有可能是两次)旋转。

            这样做的目的是,尽可能让红色节点上移,这样红色节点就会变少,此时插入黑色需要调整的就少了

         

         

        */

        

        

        //一下是算法导论中的红黑树笔记:

        

        

        //哨兵

        /*

            哨兵:

            为了方便处理红黑树中的边界条件,使用一个哨兵(T.nil)来表示叶子节点,T.nil拥有和普通节点一样的属性

            color属性为black,其他属性可以为任意值,这样可以把叶子节点视为一个普通的节点,但是为了节省空间,可以把

            所有叶子节点和根节点的父节点设置为同一个哨兵(T.nil)

         

        */

        

        

        //红黑树的高度

        /*

            树高h最大为2lg(n+1):

            先用归纳法证明每个x节点至少包含 2^(bh(x))-1 个子节点(bh==blackheight)

            1:如果bh(x)0,也就是xT.nilx拥有 2^(0)-1 == 0个子节点

            2:一个x的子节点的黑高为 bh(x):{x为红色} bh(x-1):{x为黑色}

            所以x拥有的自节点个数至少为 2*2^(bh(x)-1)-1 == 2^(bh(x))-1

            由此得证:每个x节点至少包含 2^(bh(x))-1 个子节点

            

            根据第3个条件,一条路径至少包含一半的黑色节点 -->>

            bh(x)>=h/2 -->>  n>=2^(h/2)-1 -->> lg(n+1) >=h/2 

            -->> h<=2lg(n+1) (lg表示log2)

            得证树高最大为2lg(n+1)

            所以RB_tree所有操作时间为O(lg(n));

         

         

        */

        

        //左旋转操作

        

        //x进行左旋转

        LEFT-ROTATE(T,x)

        {

            y=x.right;          //拿到x的右儿子

            x.right=y.left;     //已知的有 x.right==y y.p==x 所以可以先改变这两个值

            if(y.left!=T.nil)   //如果y的左儿子为nil就不需要给这个nil赋值一个parent

                y.left.p=x;

            

            y.p=x.p;            //剩下的已知只有y.p  所以找到旋转后的y.p就是现在的x.p

            if(x.p == T.nil)    //如果x.pnil,代表x时根节点,所以旋转后y就是根节点

                T.root=y;

            else if(x=x.p.left) //判断x是的父节点的左儿子还是右儿子

            {

                x.p.left=y;

            }

            else

            {

                x.p.right=y;

            }

            y.left=x;           //y.left用完了(之前给x.right赋值完就可以存放x),拿来存放旋转后的值(x);

            x.p=y;              //x.p用完了,可以拿来存放旋转后的值(y)

        }

        

         

  • 相关阅读:
    C#开发规范
    Win32API使用技巧 -- 置顶应用
    Windows开发常用快捷键
    MarkDown简单语法回顾
    样本分布
    复变函数
    set theory
    Oscar的数理统计笔记本
    Oscar的拓扑笔记本
    c语言总结
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983168.html
Copyright © 2011-2022 走看看