zoukankan      html  css  js  c++  java
  • 一个红

    文章引用《算法导论》
    自然红黑树
        红黑树是一棵二叉搜索树,它在每一个节点上添加了一个存储位来表示结点的颜色。能够是RED或者是BLACK。红黑树确保没有一条路径会比其他路径长2倍。因而是近似平衡的
        树中的每一个结点包括5个属性:color、key、left、right、parent,假设一个结点没有子结点或者是父结点,则该结点对应指针属性的值为NIL。能够把NIL视为指向二叉搜索树
    的也结点的指针,而把带有keyword的结点视为树的内部结点。
    一棵红黑树是满足以下红黑性质的二叉树:
    1. 每一个结点或是红色的。或是黑色的。
    2. 根节点是黑色的。
    3. 每一个叶结点(NIL)是黑色的。
    4. 假设一个结点是红色的,则它的两个子结点都是黑色的。
    5. 对每一个结点。从该结点到其全部后代叶结点的简单路径上,均包括同样数目的黑色结点。
    规定:从某个结点x出发(不含该结点)到达一个叶结点的随意一条简单路径上的黑色结点个数称为该结点的黑高(black-height),记为bh(x)。

    引理:一棵有n个内部结点的红黑树的高度至多为2lg(n+1)
    一棵使用了公共结点的红黑树例如以下:

    旋转


    1、左旋转

    LEFT-ROTATE(T,x)
    y = x.right	//set y
    x.right = y.left	//set x.right
    if y.left != T.nil
    	y.left.p = x
    y.p = x.p	//link x's parent to y
    if x.p == T.nil
    	T.root = y
    elif x.p == x.p.left
    	x.p.left = y
    else
    	x.p.right = y
    y.left = x	//put x on y's left
    x.p = y

    2、右旋转

    RIGHT-ROTATE(T,y)
    x = y.left	//set x
    y.left = x.right
    if x.right != T.nil
    	x.right.p = y
    y.p = x.p	//link y's parent to x
    if y.p == T.nil
    	T.root = x
    elif y.p == y.p.left
    	y.p.left = x
    else
    	y.p.right = x
    x.right = y	//put y on x's right
    y.p = x

    红黑树的插入

            我们能够在O(lgn)时间内完毕想一棵含n个结点的红黑树中插入一个新的结点。

    为了做到这一点,利用TREE-INSERT过程,将结点z插入树T中,

    就好像T是一棵普通的二叉搜索树一样,然后将z着为红色,为了能保持红黑性质。我们设计了一个辅助程序RB-INSERT-FIXUP来对结点又一次着色并
    旋转。

    RB-INSERT(T,z)
    y = T.nil
    x = T.root
    
    if x != T.nil
    	y = x
    	if z.key < x.key
           		x = x.left
    	else
    		x = x.right
    z.p = y
    
    if y == T.nil
    	T.root = z
    elif z.key < y.key
    	y.left = z
    else
    	y.right = z
    z.left = T.nil
    z.right = T.nil
    z.color = RED
    RB-INSERT-FIXUP(T,z)

    红黑树的修订

    RB-INSERT-FIXUP(T,z)
     while z.p.color == RED
    	if z.p == z.p.p.left
    		y = z.p.p.right
    		if y.color == RED                
    			z.p.color = BLACK     //case 1
    			z.p.p = RED               //case 1
    			y.color = BLACK        //case 1
    			z = z.p.p                    //case 1
    		else if z == z.p.right
    			z = z.p                       //case 2
    			LEFT-ROTATE(T, z)   //case 2
    		else
    			z.p.color = BLACK   //case 3
    			z.p.p.color = RED   //case 3
    			RIGHT-ROTATE(T, z.p.p)   //case 3
    	else
    		y = z.p.p.left
    		if y.color == RED
    			z.p.color = BLACK
    			y.color = BLACK
    			z.p.p.color = RED
    			z = z.p.p
    		else if z == z.p.left
    			z = z.p
    			RIGHT-ROTATE(T,z)
    		else
    			z.p.color = BLACK
    			z.p.p.color = RED
    			LEFT-ROTATE(T,z.p.p)
    T.root.color = BLACK




            在调用RB-INSERT-FIXUP操作时。哪些红黑性质可能会被破坏呢?性质1和性质3继续成立。由于新插入的红姐点的两个子结点都是哨兵T.nil。性质5,即从一个制定结点開始的每条
    简单路径上的黑节点的个数都是相等的。也会成立。由于结点z取代了(黑色)哨兵,而且结点z本省是哨兵孩子的红姐点。这样开来。仅可能被破坏的就是性质2和性质4,即根结点须要为黑
    色以及一个红结点不能有哄孩子。这两个性质可能被破坏是由于z被着为红色。

    假设z是根节点,则破坏了性质2;假设z是父结点是红结点,则破坏了性质4。

            在1~15行中的while循环在每次迭代的开头保持下列3个部分的不变式:
    1. 结点z是红结点。
    2. 假设z.p是根结点,则z.p是黑结点。

    3. 假设有不论什么红黑性质被破坏。则至多仅仅有一条被破坏,或是性质2,或是性质4.假设性质2被破坏,则原因是z是根结点且是红结点。

      假设性质4被破坏。其原因是z和z.p都是红结点。

    证明循环不变式

    红黑树的5个性质:
    1. 每一个结点或是红色的。或是黑色的。
    2. 根节点是黑色的。

    3. 每一个叶结点(NIL)是黑色的。
    4. 假设一个结点是红色的,则它的两个子结点都是黑色的。

    5. 对每一个结点,从该结点到其全部后代叶结点的简单路径上,均包括同样数目的黑色结点。

            初始化:在循环的第一次迭代之前,从一棵正常的红黑树開始,并新增一个红结点z。
            要证明当RB-INSERT-FIXUP被调用时,不变式的每一个部分都成立,下面是循环不变式。
    • 当调用RB-INSERT-FIXUP时,z是新增的红结点。
    • 假设z.p是根。那么z.p開始是黑色的,且在调用RB-INSERT-FIXUP之前保持不变。

    • 注意在调用RB-INSERT-FIXUP时,性质1、性质3和性质5成立。

            假设违反了性质2,则红色根结点一定是新增结点z。它是树中唯一的内部结点。由于z的父结点和两个子结点都是黑色的哨兵。没有违反性质4.这样,对性质2的违反是整棵树中唯一违
    反红黑性质的地方。
            假设违反了性质4。则由于z的子结点是黑色哨兵。且该树在z增加之前没有其他性质的违反。所以违反必定是由于z和z.p都是红色。并且。没有其他性质被违反。
            终止:循环终止是由于z.p是黑色的。这样。树在循环终止时没有违反性质4.依据循环不变式,唯一可能不成立的是性质2。

    第16行恢复这个性质。所以当RB-INSERT-FIXUP终止时,所

    有的红黑性质都成立。
            保持:实际须要考虑while循环中的6种情况,而当中三种和另外三种是对称的。取决于z的父结点z.p是z的祖父结点z.p.p的左孩子还是右孩子。

    依据循环不变式的第二条,假设z.p是根

    结点。那么z.p是黑色的,可知结点z.p.p存在。

    由于仅仅有z.p是红色时才进入一次循环迭代,所以z.p不可能是根结点。

    因此。z.p.p存在。

            情况1和情况2、情况3的差别在于z父亲的兄弟结点的颜色不同。第3行使y指向z的叔结点z.p.p.right,在第4行測试y的颜色。假设y是红色的,那么运行情况1.否则,控制转向情况2和3.
    在全部三种情况中,z的祖父结点z.p.p是黑色的,由于它的父结点z.p是红色的。故性质4仅仅在z和z.p之间被破坏。
    1. 情况1: z的叔结点y是红色

            a.由于每次迭代把z.p.p着为红色,结点z.p.p.p在下次迭代的開始是红色。
            b.在这次迭代中结点z.p.p.p,且这个结点的颜色不会改变。假设它是根结点,则在此次迭代之前它是黑色,且在下次迭代的开头任是黑色。

            2.情况2:z的叔结点y是黑色的且z是一个右孩子
            3.情况3:z的叔结点y是黑色的且z是一个左孩子


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    ssh免密登录
    idea搭建flink环境
    idea快捷键列表
    scala对复杂json的处理
    配置三台服务器的时间同步-linux 及 ntp.conf配置文件详解
    91. Reverse Linked List 反转链表
    92. Reverse Linked List II 反转链表 II
    121. Best Time to Buy and Sell Stock 买卖股票的最佳时机
    53. Maximum Subarray最大子序和
    70. Climbing Stairs爬楼梯
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4850086.html
Copyright © 2011-2022 走看看