zoukankan      html  css  js  c++  java
  • 数据结构 红黑树二

    插入操作

            我们可以用类似于二叉搜索树的方法来向树中插入一个元素。它可以在O(lgn)时间内完成,所谓插入就是将新结点插入为叶子节点,从根节点开始遍历。

    // 插入
    RB_INSERT(T, z)
        y = T.nil
        x = T.root
        while x != T.nil             // 找到合适的插入父节点
            y = x                    // y 一定是叶子节点
            if z.key < x.key
                x = x.left
            else
                x = x.right
    
        z.p = y                      
        if y == T.nil                // y == T.nil 说明红黑树是空树
            T.root = z
        else if z.key < y.key        // 找到合适的位置挂载z
            y.left = z               // 此前 y.left 一定是 T.nil
        else
            y.right = z
    
        z.left = T.nil               // 初始化z节点
        z.right = T.nil
        z.color = RED
        RB_INSERT_FIXUP(T, z)       // 红黑树再平衡

    备注:插入操作一定是将z当成一个叶子节点插入

    可以看出我们默认把新插入的结点着为红色插入(原因之后给出)。与二叉搜索树的插入算法最为不同的是,

    在最后一步我们调用了RB-INSERT-FIXUP方法来维护红黑树的性质。

    // 插入再平衡
    RB_INSERT_FIXUP(T, z)
    while z.p.color == RED if z.p == z.p.p.left // 父节点是左孩子 u = z.p.p.right // y是叔叔节点 if u.color == RED z.p.color = BLACK // case1 y.color = BLACK // case1 z.p.p.color = RED // case1 z = z.p.p // case1 else if z == z.p.right z = z.p // case2 LEFT_ROTATE(T, z) // case2 z.p.color = BLACK // case3 z.p.p.color = RED // case3 RIGHT_ROTATE(T, z.p.p) // case3 else // same T.root.color = BLACK

    说明:

           上述过程可能有些复杂,我们来仔细分析一下,从两个方面入手。

        第一,我们应当明确RB_INSERT_FIXUP方法是来维护红黑树的性质的,因此我们要搞清楚插入一个结点(红色)将会打破哪些性质;

        第二,我们要具体分析上述的三种情况究竟在做什么、有什么影响。

    哪些性质会被破坏

        很明显,只有性质①——根结点必须是黑色和性质②——红色结点的孩子必为黑色会被破坏。

    三种情况

        首先,循环的大前提是z的父结点是红色,父节点是黑色,满足红黑树性质,不需要处理。然后,我们分析的三种情况建立在z的父结点是左孩子基础上(相反情况类似,不做分析)。

     我们还容易看出:在每次迭代前,z节点总是红色的;y节点为z节点的“叔叔”(y = z.p.p.right,下面称y为z的叔节点)。

    Case 1:z的叔节点y为红色(同时也说明了z的“爷爷”节点是黑色的)。

    在做什么:把z的“爷爷”节点着为红色;而把“爷爷”节点的子节点都着为黑色;z上升2级,指向它的“爷爷”节点。

    有什么影响:修复了z节点附近的红黑树性质,但是破坏了z爷爷节点附近的红黑树性质,通过z指向爷爷节点,

    可以通过循环继续修复z爷爷节点附近的红黑树性质,黑高没有变化

    Case 2:z的叔节点y为黑色且z为右孩子。

    在做什么:z指向自己的父节点;对z节点进行左旋操作。

    有什么影响:为了构造case3的场景,黑高没有变化

    Case 3:z的叔节点y为黑色且z为左孩子。

    在做什么:把z的父节点置为黑色;把z的“爷爷”节点置为红色;对z的“爷爷”节点进行右旋操作。

    有什么影响:修复红黑树的性质,黑高没有任何变化

    具体分析如图

    /*------------------case2+case3分析-------------------------------------*/

    小结:

    由于我们默认把新插入的结点置为红色,因此初始时,结点z是红色显然成立。在迭代之前,如果只有一个结点,即只有根结点,性质①被打破;

    否则,z和z.p都为红色,性质②被打破;

    从上面对三种情况的分析我们可以看出:结点z始终是红色的;三种操作都没有改变任何路径上的黑高,即性质③始终是满足的。

    显然每次完成case 1后,性质①或性质②是被打破的。完成case 2一样。当完成case 3后,循环就终止了(因为在case 3中我们把z.p置为了黑色),此时满足红黑性质。

    由于一棵有n个结点的红黑树的高度为O(lg n),因此执行RB—INSERT需要O(lg n)时间;在RB-INSERT-FIXUP中,

    仅当case 1发生时,while循环才会执行下去;而每次执行完case 1,指针z都会上升2层。

    因此while循环最多执行lg n次;所以RB-INSERT-FIXUP时间复杂度为O(lg n),因此整个插入操作的时间复杂度为O(lg n)。

  • 相关阅读:
    python操作excel文件一(xlrd读取文件)
    pytest 1.简单介绍一,安装和如何运行
    request鉴权的处理和判断
    Struts2 easy UI插件
    Struts2 JQuery UI常用插件
    Struts2 JSON
    Struts2 使用jQuery实现Ajax
    Struts2 Ajax校验
    oracle连接方式、创建数据库用户、忘记数据库密码、用户锁定
    第二次考试:错题总结
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/14691481.html
Copyright © 2011-2022 走看看