赤黒木 (21)
昨晩、以下をトレイス中に力尽きた模様。
以下を再度確認してみます。
;; preparation ;; B:-2 => -2 ;; R:-1.5 => -1.5 ;; R:-1 => -1 ;; B:-0.5 => -0.5 ;; B:0 => 0 ;; R:0.5 => 0.5 ;; B:1 => 1 ;; B:2 => 2 ;; B:2.5 => 2.5 ;; B:3 => 3 ;; B:3.5 => 3.5 ;; R:4 => 4 (i -0.5 -1) ;; case 7a deleting black node, which is a left child of its parent, ;; and its sibling is black, and sibling's left child is red. ;; This goes through a nested if-statement in delete_node1() ;; and involves swapping sibling. (test* "deletion case7a" #t (begin (d -2) (c))) ;; case 4b. deleting black node, whose sibling is red. (test* "deletion case4b" #t (begin (d 0.5 1) (c))) ;; case 3. this goes through parent==NULL stop condition in the ;; loop in delete_node1. ;; B:-1.5 => -1.5 ;; R:-0.5 => -0.5 ;; B:0 => 0 ;; B:2.5 => 2.5 ;; R:3 => 3 ;; B:3.5 => 3.5 ;; R:4 => 4 (test* "deletion case3" #t (begin (d 2 -1) (c)))
纏め作りたいんだけどなぁ。とは言え、台風云々のおかげかどうか不明ですが、色々な意味でへろへろ。これから台風が、という方々におかれましてはくれぐれもご注意下さい。そしてあまり被害がないことを祈っております。
最初から再開
まず最初の状態から B:-2 な要素の削除。確かにケイス的に 7a ですね。sibling な B:-0.5 が赤になり、その左側の子供の色が黒になって rotate_right される模様。
;; R:-1.5 => -1.5 ;; B:-1 => -1 ;; R:-0.5 => -0.5 ;; B:0 => 0
R:-0.5 を基に rotate_right なので以下か
;; R:-1.5 => -1.5 ;; B:-1 => -1 ;; R:-0.5 => -0.5 ;; B:0 => 0
で、sibling が B:-1 に切り替わって 8a 通過なのか。こうなるのかな。
;; B:-1.5 => -1.5 ;; R:-1 => -1 ;; B:-0.5 => -0.5 ;; B:0 => 0 ;; R:0.5 => 0.5 ;; B:1 => 1 ;; B:2 => 2 ;; B:2.5 => 2.5 ;; B:3 => 3 ;; B:3.5 => 3.5 ;; R:4 => 4
で次に R:0.5 削除。末端の赤なのでそのまま削除。
;; B:-1.5 => -1.5 ;; R:-1 => -1 ;; B:-0.5 => -0.5 ;; B:0 => 0 ;; B:1 => 1 ;; B:2 => 2 ;; B:2.5 => 2.5 ;; B:3 => 3 ;; B:3.5 => 3.5 ;; R:4 => 4
昨晩もここまでは無事にナニできてます。次に B:1 が削除。sibling が赤ですね。あ、昨晩は最初の 8a なソレが間違っていたのか成程。まず以下な状態になって
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; B:-0.5 => -0.5 ;; R:0 => 0 ;; B:2 => 2
削除対象は右なのでコメントの通り 4b ですね。R:0 を基に rotate_right されます。こうなるのかな? sibling は B:-0.5 になるのかな。
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; B:-0.5 => -0.5 ;; R:0 => 0 ;; B:2 => 2
で、8b を通過してこうなるの?
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; R:-0.5 => -0.5 ;; B:0 => 0 ;; B:2 => 2
これ、平衡ではないな。リトライ。B:1 が削除される直前の部分木が以下。parent が B:0 で sibling が R:-1 になるのか。
;; B:-1.5 => -1.5 ;; R:-1 => -1 ;; B:-0.5 => -0.5 ;; B:0 => 0 ;; B:1 => 1 ;; B:2 => 2
parent を赤、sibling を黒にして
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; B:-0.5 => -0.5 ;; R:0 => 0 ;; B:2 => 2
R:0 を基に rotate_right します。
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; B:-0.5 => -0.5 ;; R:0 => 0 ;; B:2 => 2
これ、末端側が R だったら辻褄が合うんだけどなぁ。parent が R:0 のままで sibling が B:-0.5 になり、8b ってさっきと同じだなぁ。そもそも sibling が B:-0.5 だとして黒にならないといけない sibling->left が nil だなぁ。
おそらくは、なんですが赤黒木の特徴として
- 末端赤は許容
- 末端でない赤は両方子供が居ないとまずい
- しかも両方黒でないと駄目
なので
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; B:-0.5 => -0.5 ;; R:0 => 0 ;; B:2 => 2
ってなってれば平衡なんだけどこうならないのかどうなのか。んーと、R:0.5 削除が微妙なのかな。あ、5 を通過するのかな。違う。6 だ。
リトライ
- 2 と 0.5 を削除した直後の状態が以下。
;; B:-1.5 => -1.5 ;; R:-1 => -1 ;; B:-0.5 => -0.5 ;; B:0 => 0 ;; B:1 => 1 ;; B:2 => 2 ;; B:2.5 => 2.5 ;; B:3 => 3 ;; B:3.5 => 3.5 ;; R:4 => 4
ここで B:1 が削除なのですが 4b なケイスとして
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; B:-0.5 => -0.5 ;; R:0 => 0 ;; B:2 => 2
となった後に親が赤で sibling な B:-0.5 の子供が両方黒な 6 のケイスになるのか成程。以下になって終われば
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; R:-0.5 => -0.5 ;; B:0 => 0 ;; B:2 => 2
末端赤で平衡。やれやれ。この状態で B:2 が削除になる。これ、B:0 と swap して以下な状態になるのかな。
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; R:-0.5 => -0.5 ;; B:2 => 2 ;; B:0 => 0
で、B:2 が削除。parent は B:-1 で、sibling は B:-1.5 になるのかな。これ、子供が赤なパターンだな。こうなるの?
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; R:-0.5 => -0.5 ;; B:0 => 0
で、黒に変わって以下で終了なのか。
;; B:-1.5 => -1.5 ;; B:-1 => -1 ;; B:-0.5 => -0.5 ;; B:0 => 0
うーん、これって 3 なケイスを通過してないぞ。一応赤黒的には平衡ですが。これで -1 削除でどうなるんだろ。swap_node で以下になって
;; B:-1 => -1 ;; B:-1.5 => -1.5 ;; B:-0.5 => -0.5 ;; B:0 => 0
B:-1 が削除。parent は B:-1.5 ですね。これは 5 なケイスですね。sibling な色が赤になって繰り返し。
;; B:-1.5 => -1.5 ;; R:-0.5 => -0.5 ;; B:0 => 0
で、child が B:-1.5、parent が B:0 になって 3 を通過して終了なのか。すばら。
つーことで
再度纏めに着手したいと思ってるんですが、
/* At this point, child is BLACK. */ if (parent == NULL) { DELETE_CASE("3"); return; }
な deletion case3 をパスさせるのにこんなに苦労するのか (絶句