Red-black tree - draft

--- --- restore content begins

- This is just a draft, not typesetting, before always wanted to write a paper template that has yet to be written, it is estimated that write more slowly, so first put out the article, filled pit it back again. The original intention of this article is to see the interview questions asked to have red-black tree, even Shredded red-black tree code? Scary, red-black tree is a lot of discussion, accidentally go around, really daring, and online articles are vague, many people understand or even wrong.

 

- red-black tree: red-black tree is a balanced binary tree, a binary search tree, which regressed in the fact that it is sufficient balance, can reach heights of up to 2lg (n + 1), so java in the treemap and c ++ set, multiset, map, multimap to use red-black tree. 

- Properties of red-black tree: a node is divided into two kinds of red and black is black root 2. 3. Each leaf node (nil) is black (black represents is empty) 4. Sons absent case are red (two consecutive red) 5. child to any number of black root node on the path are equal (Important)

- This article will explain the following:

 Insert (simple insert) and Adjustment 1. red-black tree (balance adjustment). 

2. Remove red-black tree (also with adjustment, making it easy to adjust the balance) and adjustment (balance adjustment).

 

### insert

#### insert mode:

  Consider the insertion node what color, the color should be noted here that we just used to ensure a balanced approach has nothing to do with the data. Because the insertion of black nodes except the root node, or will cause all child on a branch branch have one more black, so properties are not satisfied 5 (referred to as the same way black). So we inserted into the red. Insert way is to insert a normal way binary sort tree. It's that simple.

 

#### Adjustment:

  Because the insertion of relatively simple adjustments, we can put all of the circumstances enumerated and discussed, based on the list is: because the red insert nodes will not have any impact on the insertion node's children (ie, consistent with the nature 1-5, when I when making any assertion, it is best for yourself), so the case of the insertion node ancestors only consideration.

(Figure too much, we do hand-painted sorry) 

 

Specifically, we need to do is some discussion after the interval, it must meet all cases are still adjusting the balance of ancestors and descendants are concerned, because the original two are balanced, so just to ensure that the discussion is in the interval the left and right subtrees meet any nature, and does not change the original ancestor and interfaces and sub-tree, then we will be able to maintain the same nature.

 

 From left to right, are red, black, any color, additional black (meaning that in addition to the color of the original node having additionally a layer of black, useful when used later repeat),

Not shown in the figure does not mean that the son of the son node is nil, if the leaf node monogram nil.

 The figure below shows all cases

 

Case 1: a single node, has no parent node.

 

 

 

Adjustment: red to black, 2 properties (referred to as black root),

Case 2: the parent node is black, so inherently balanced, but because of the son node question may be red, this situation can be converted to its discussion son, the parent node of its sons is red, then the corresponding case 3 down just discussed, it should be considered a sub-case 2 case 3 case.

 

Case 3: The parent node is red

Divided into two cases, one parent's right child, a parent of a child is left.

 

 

 

 

    

 

In the case of 3.1.1 ,   simply uncle node and the parent node becomes black, and the node becomes red grandfather, we can maintain a consistent two branches black node, and no two of red, can meet all the controls nature, which is considered a good recovery, but only for the sub-tree diagram at the top of the node, if the adjusted top of the red nodes as a subject for discussion, to discuss his parent node case, they can recursively Classified discussion recovery , the actual algorithm is recursive calls.

 

In the case of 3.1.2 manner similar to 3.1.1

 

对于情况3.1.3, 可以先以红-红中的父节点进行左旋转,然后和情况3.2.3一样了,只需再以它为中心右旋一次,并如图变换颜色即可,最重要的依据就是分支的黑色要一致。所以调整后整棵树就恢复好了。因为讨论区间分别和子树以及子树连接的部分的红色维持不变,所以不会影响到原本的祖先和子孙的平衡情况。

 

 

 

对于其他情况,可以类似上面的四种情况进行操作,不再一一介绍,为了和教科书上(算法导论)保持一致,并且简化情况,我们需要将多种情况进行合并。合并的最后结果只剩下三种情况。如图中棕色的标号, (要记就记以下的结果)

①代表了第一种情况,这里把只有一个红色结点的情况归类为了父节点为黑色,实际上也是这么定义的,根节点的父节点为nil,nil为黑色,这样就进行了统一。

①归纳了情况:插入节点的父和叔节点是红色时,把他们变黑,再把爷爷变红,递归调用爷爷作为参数继续算法,

 

 

②归纳了情况:插入节点的父是红色uncle是黑色时,如果自己是父的右结点,先左旋到情况③

 

③归纳了情况:自己是父的左结点)然后再把fauncle变成黑色,grandparent变成红色再以父亲为参数右旋

 

 

 

 对应的还有①', ②',③',它和①, ②,③的区别就在于讨论的结点是在左子树还是右子树,操作方法是对称的,所以恢复算法一共有六种情况,但是三种也对。

 附上代码:

#插入方法
RB-INSERT(T,z): #z就是插入的结点也是fix时当前讨论的结点
    y = T.nil
    x = T.root
    while 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
    else if 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)
View Code

 

 

View Code

 

---

 

### 删除:

删除情况讨论如果按照之前的将所有情况都讨论出来,那会很累,并且会绕进去, 所以我们还是根据现有的算法,来讨论分类

##### 删除的方式:根据情况删除时就做一些调整。

##### 主要的讨论分类方式:将删除分类为1.如果删除的结点只有一个孩子(不考虑nil),又可继续讨论下去,那个孩子是左孩子还是右孩子,

2.如果删除的结点有两个孩子,同样也可详细讨论  ,当然你也可以说还有一种情况,如果删除的结点一个孩子都没有,那种情况只用单纯的删除,删除过程中没有进行额外的操作,所有删除操作都要进行删除步骤,所以这里不进行讨论,注意到我们仅讨论了删除节点为根的子树情况,而没有讨论它的祖先结点,不是因为不影响,而是在删除过程中仅需要对以上几种情况分开讨论以进行额外的操作,便于删除恢复。 

##### 删除的具体情况: 删除过程我们的主要目的是保证通过一些方法让整棵树仍然保持平衡(加附加黑的方式),然后在恢复的过程中解决附加黑的问题,以下讨论中a为待删除结点

删除掉a,将另一个结点作为替换,因为 原来的a结点可能就是黑色的,这样a的子树就少了一个黑色,所以将b涂成黑色。我们发现这种情况就不再需要调整了。已经满足了要求的各种性质,不信可以试试。

 

如果有两个孩子的话,并且 a(待删除结点)的儿子结点的左儿子为nil,就说明a是c最小的后继,删除a后,将c移动到a的位置,当然也可以用a的左子树中最大的数即a的前驱来替换他。除此之外,这种情况下,c必须和a的颜色相同,目的是使得改动最小,但是当a是黑色的时候,由于c,d根据性质必有一黑,当c是黑时,c替换后,c的分支相对于原来,少了一个黑色的结点,这时候就需要多加一重黑色来保证平衡

 

 

如果有两个孩子,并且a的儿子结点的儿子结点不为空,那么,通过找到左儿子的最小值,即dfs一直找最左儿子为nil的d,将它和a进行交换,然后e代替nil,同理还是d代替a的颜色,这时a为黑,且d为黑时就会不平衡,这时候如同情况2也需要给e多加一层黑色。

 

算法中①的情况因为左为nil和右为nil操作虽然对称,但是不一样,所以一般分成四种情况

 

 

#####  删除恢复,

最激动人心的时刻,删除恢复,不知是谁想的附加黑色这种骚操作,经过了上面的删除,我们现在只需要考虑恢复的情况只有如何将附加黑情况进行处理,基本思路是只考虑附加黑结点的子树以外的结点,因为算法试图将附加黑不断向树根传递,来达到在某一部消除的方式来恢复。

具体的讨论情况分为 附加黑结点的兄弟是1.红,2.黑(有分为三种情况: 1。兄弟的儿子为全黑 2.左红右黑 3.左any右红 )自己画画是否讨论完全了。 这样算一共4种子情况如下: 

情况1:

这种情况是 附加黑的兄弟是红色,进行左旋,对应了第二大类的讨论。

 

情况2:

兄弟为黑,并且兄弟儿子全黑,这时候将附加黑向上传递,这样右边就多了一重黑色,所以将c改成红色,b的子树就满足要求了,然后继续以b为结点进行递归

 

兄弟为黑并且左红右黑,通过以c为中心右旋再交换dc颜色就达到了情况4

情况4: 

 

 

通过以b为中心左旋,这时我们发现左边和右边确定的黑分别为2和1,原来是1和1,所以需要给右边增加一层黑,通过将附加黑给b让b称为黑色,同时使得e为黑色,这样就满足了左2黑右2黑,但是要保持原来的黑色数为1,所以就将c改成原来b位置应有的任意

 

 

- 以上四种情况只考虑了a(带附加黑的点)是左儿子的情况, 同样右儿子是对称,所以和插入一样,4种基本情况实际是2x4种详细情况

 

以下为删除的伪代码:

RB-DELETE(T,z):
    y = z
    y-origin-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-MINIMUN(z,right)
        y-original-color = y.color
        x = y.right
        if y.p == z
            x.p = y
        else RB-TRANPLANT(T,y,y.right)
            y.right = z.right   
            y.right.p = y
        RB-TRANSPLANT(T,z,y)
        y.left = z.left
        y.left.p = y
        y.color = z.color
        if y-original-color ==BLACK
            RB-DELETE-FIXUP(T,x)
View Code
 

 

RB-DELETE-FIXUP(T,x)
    while x!=T.root and x.color ==BLACK:
        if x== x.p.left
            w = x.p.right
            if w.color ==RED                                                     # case 1
                w.color = BLACK
                x.p.color = RED
                LEFT-ROTATE(T,x.p)
                w  = x.p.right
            if w.left.color ==BLACK and w.right.color ==BLACK 
                w.color = RED                                                    #case 2
                x = x.p
            else if w.right.color ==BLACK
                w.left.color =  BLACK                                         #case 3
                w.color = RED
                RIGHT-ROTATE(T,w)
                w = x.p.right
            w.color = x.p.color                                                 #case 4
            x.p.color = BLACK
            w.right.color = BLACK
            LEFT-ROTATE(T, x.p) 
            x = T.root         
        else  (same as then clause with "right" and left exchanged )   #symetric case
    x.color = BLACK                
View Code

 

Guess you like

Origin www.cnblogs.com/captainhook/p/11681219.html