赤黒木 (24)

纏めに三度着手。の前に赤い要素の仕様を。

  • 末端赤は許容
  • 末端でない赤は左右両方に黒の要素を持つ

という理解だけど良いのかどうか。

とりあえず

case4 以降の条件を整理してみます。case2 以降は削除対象要素は黒限定となります。

  • case4 は削除対象の要素の sibling な要素が赤
  • case5 は親が黒で削除対象要素の sibling の子供が両方黒
    • At this point, sibling is BLACK というコメントがある件
  • case6 は親が赤で削除対象要素の sibling の子供が両方黒
  • case7a は削除対象要素がその親の左側の子供でその sibling な要素の子供の左側が赤で右側が黒
  • case7b は削除対象要素がその親の右側の子供でその sibling な要素の子供の左側が黒で右側が赤
  • case8 は case4 および case7 の場合実行される後処理

これ的情報は昨晩エントリにもありますね。

むむむ

駄目だ。追いかけてた中で分かったことを列挙してみると

  • case4 あるいは case7 の後、sibling の削除対象の逆側の子供は存在している
    • もしかしたら赤かも

試験から確認してみます。4a の試験で最初の状態が以下。

  ;;      B:-2 => -2
  ;;    B:-1 => -1
  ;;        B:-0.7 => -0.7
  ;;      R:-0.6 => -0.6
  ;;          R:-0.5 => -0.5
  ;;        B:0 => 0

ここから B:-2 な要素を削除。親 (B:-1) を赤にして sibling なソレ (R:-0.6) を黒に。

  ;;    R:-1 => -1
  ;;        B:-0.7 => -0.7
  ;;      B:-0.6 => -0.6
  ;;          R:-0.5 => -0.5
  ;;        B:0 => 0

で、親を基点に rotate_left して以下?

  ;;      R:-1 => -1
  ;;        B:-0.7 => -0.7
  ;;    B:-0.6 => -0.6
  ;;        R:-0.5 => -0.5
  ;;      B:0 => 0

あ、ここで 6 のケイスと評価されるのか。必ず 8 って訳ではないのね。ここから R:-1 が黒になって B:-0.7 が赤になって以下。

  ;;      B:-1 => -1
  ;;        R:-0.7 => -0.7
  ;;    B:-0.6 => -0.6
  ;;        R:-0.5 => -0.5
  ;;      B:0 => 0

必ず 4* から 8 という訳ではないのか。この場合、6 を通って終わってますね。むむむむ的。あら、昨晩の 4b なケイスも 6 になって終了してますね。7* は必ず 8 を通過するのは当り前なんですが、4* からは必ず、という訳ではないのか。
む、6 を通過するのは slibing の子供が両方黒というケイスなのか。うーん、やはりこのあたりの条件を色々確認しないとアレですね。

それぞれのケイスが

実行される条件とその結果を纏めないとアレ。つうかその前に赤い node の仕様を列挙しましたが黒い node の仕様は以下になるのかな。

  • 黒 node は子供を持たない場合がある (これは赤 node も同様)
  • 黒 node は赤い子供 node を片方のみ持つ場合がある
  • 黒 node は黒い子供 node を片方のみ持つことは無い
  • 黒 node は左右に子供を持つ場合、全ての組み合せの可能性があり得る
    • 赤-赤、黒-赤、赤-黒、黒-黒
  • sibling な node についても nil を含めて全ての可能性があり得る

うーん。1 から順にいくつか追加してみて確認してみます。まず空の木に R:1 を追加したら以下に。

B:1

次に 2 な要素追加。

B:1
  R:2

次に 3 な要素追加。

B:1
  R:2
    R:3

親が赤。親はその親の右側の要素。親の sibling は nil です。あら? 右に回転しとるな、と思ったら b は #f だった。こうなるのか。

  R:1
B:2
  R:3

次に 4 が追加。

  R:1
B:2
  R:3
    R:4

同じカンジかな。ただ、親の sibling は nil ではないですね。あ、赤なので繰り返すのかな。R:3 を黒にして R:1 も黒にして B:2 を赤にして

  B:1
R:2
  B:3
    R:4

R:2 が z に渡されて繰り返し。最後に R:2 が黒になって終了か。

  B:1
B:2
  B:3
    R:4

次に R:5 を追加。

  B:1
B:2
  B:3
    R:4
      R:5

今度は親の sibling は nil か。こうなって

  B:1
B:2
  R:3
    B:4
      R:5

R:3 基点で左回転。

  B:1
B:2
    R:3
  B:4
    R:5

追加は基本、一直線にして上の状態にするのが基本なのかな。あとは B:4 先頭な部分木について R:4 追加したときと同じ形になるはず。

  B:1
B:2
    R:3
  B:4
    R:5
      R:6

ええと、親を黒にして、親の sibling も黒にして B:4 は赤にして繰り返し。

  B:1
B:2
    B:3
  R:4
    B:5
      R:6

を、でもこんどは二回繰り返しが続くな。でも親が黒なのでこれで終わりなのか。ちなみにこの状態で R:5.5 を追加すると

  B:1
B:2
    B:3
  R:4
    B:5
        R:5.5
      R:6

ここから一直線に修正して

  B:1
B:2
    B:3
  R:4
    B:5
      R:5.5
        R:6

こうなります。

  B:1
B:2
    B:3
  R:4
      R:5
    B:5.5
      R:6

そろそろ root が変わらんかな。

  B:1
B:2
    B:3
  R:4
      R:5
    B:5.5
      R:6
        R:7

親が赤、親の sibling も赤。こうなって

  B:1
B:2
    B:3
  R:4
      B:5
    R:5.5
      B:6
        R:7

繰返し。R:5.5 が z になるのか。親も赤。親の sibling は黒。親を黒にして親の親を赤にして root な要素を基点に左回転。

  B:1
R:2
    B:3
  B:4
      B:5
    R:5.5
      B:6
        R:7

こうなるのか。

    B:1
  R:2
    B:3
B:4
    B:5
  R:5.5
    B:6
      R:7

もっかい確認

ええと R:6 を追加した後の状態が以下なんですが

  B:1
B:2
    B:3
  R:4
      R:5
    B:5.5
      R:6

ここに B:5.5 な部分木について要素を追加したらバランスが崩れるので root が変更になるほどの回転が発生するはず。ちなみに繰り返しが発生する条件としては追加する要素の親の sibling が赤だった場合。この状態ですね。

      R:5
    B:5.5
      R:6

こうなってたら全部色を切り換えて、てことか。ここに例えば 7 を追加するケイスだと単純に回転するのみか。

    B:5.5
      R:6

で、例えば B:1 とか B:3 な部分木に要素が追加される場合はそのまま、なのか。

これを踏まえて

削除なナニを確認してみたいんですが今日は限界かなぁ。む、基本的にこんなケイスはあり得ない、のかな。。

  ;;        R:-1 => -1
  ;;      B:0 => 0
  ;;        B:1 => 1

部分木としてあり得るパターンというのは確認してみる必要があるのかどうか。あるいはそんなに単純な話になるのかどうなのか。