freebsd rb.h insert を読んでみよう2

前回は左に赤が二つつながる場合を見ました。

http://yamshing.hatenablog.com/entry/2015/09/30/205603

今回は右に赤が来る場合です。

では読んでみましょう。

    a_type *right = pathp[1].node;     //次のノードを
 rbtn_right_set(a_type, a_field, cnode, right); //右にセット
 if (rbtn_red_get(a_type, a_field, right)) {    //そのノードが赤なら
 a_type *left = rbtn_left_get(a_type, a_field, cnode);   //そしてその左が

 if (rbtn_red_get(a_type, a_field, left)) {        //赤なら
            /* Split 4-node. */                    \
            rbtn_black_set(a_type, a_field, left);        //左を黒
            rbtn_black_set(a_type, a_field, right);        //右を黒に
            rbtn_red_set(a_type, a_field, cnode);        //親を赤にします

 

つまり

  黒

赤   赤

なら

  赤

黒   黒

にするということですね。

    } else {                        //左が赤でないなら(黒か無しなら)
      /* Lean left. */                    \
      a_type *tnode;                    \
      bool tred = rbtn_red_get(a_type, a_field, cnode);    //親の色を覚えて
      rbtn_rotate_left(a_type, a_field, cnode, tnode);    //左回りで新しい親をtnodeへ
      rbtn_color_set(a_type, a_field, tnode, tred);    //その新しい親を前の親の色に塗ります
      rbtn_red_set(a_type, a_field, cnode);       //前の親は赤に
      cnode = tnode;                    //前の親を今の親に変更
 }    

 ここは

  黒/赤

黒/無  赤

という状態です。

親の色を覚えておいて左回り

 

   赤

 黒/赤

黒/無

 

覚えておいた色を前の親にそして前の親を赤にします。

 

   黒/赤

  赤

黒/無

 

そして最後に

    rbtree->rbt_root = path->node;          //今の親をルートに
    rbtn_black_set(a_type, a_field, rbtree->rbt_root);  //ルートを黒にします。

以上が挿入です。

まとめてみると

 

左に赤が2つ連続する

左と右が赤

左が赤以外右に赤が2つ連続する

左が赤以外黒赤となる

 

4つのパターンがありそうです。

左が赤以外右に赤が2つ連続するパターンは

左に回転すると左に赤が2つ連続するパターンになるので

3つのパターンでしょうか。

次回はちょっと複雑になる削除を見ていきましょう。