Slide 1

Slide 1 text

42Tokyo:STLコンテナ再実装課題 補助資料 赤黒木を理解する nfukada (nafuka11)

Slide 2

Slide 2 text

目次 赤黒木とは 01 赤黒木のルール 02 赤黒木の操作:挿入 03 赤黒木の操作:削除 04 2 最後に 05

Slide 3

Slide 3 text

赤黒木とは 目次 01

Slide 4

Slide 4 text

01 赤黒木とは 赤黒木とは ● 平衡二分探索木の一種 ● 主に連想配列(STLコンテナのmapも連想配列)の実装に使われる → 平衡二分探索木とは? → まず、木とは何かを説明する 4

Slide 5

Slide 5 text

ざっくり言うと木のようなデータ構造 - 節点(node) データが入った1要素 - 根(root) 頂点にあたるノード 使うときは根だけ持っておいて、 根から各ノードを辿っていく - 枝(edge) ノードとノードのつながり ポインタで表現する - 葉(leaf) 末端のノード 木とは 01 赤黒木とは 5 根(root) 枝(edge) 節点(node) 葉(leaf)

Slide 6

Slide 6 text

ノードの関係は親子関係に見立てて表現される ● 親:見ているノードの一つ上 ● 兄弟:親が同じノード ● 子:一つ下のノード などなど…… ノード間の関係 01 赤黒木とは 6 親 兄弟 子

Slide 7

Slide 7 text

木の中でも、 ノードから枝が最大2本までしか生えない木 二分木とは 01 赤黒木とは 7

Slide 8

Slide 8 text

「左の子孫の値 < 親の値 < 右の子孫の値」というルールを持った二分木  (大小関係には<=も含みますが、今回は簡単にするため<にしています) 大小関係を枝の左右で表していて、ノードを全て見なくても検索ができる 二分探索木とは 01 赤黒木とは 8 6より小さい 6より大きい 3より小さい 3より大きい 7より大きい

Slide 9

Slide 9 text

例:5を探すとき 6つノードがあるが、 2回ノードを辿れば5に到達できる 二分探索木とは 01 赤黒木とは 9 6より小さい 3より大きい 根からスタート

Slide 10

Slide 10 text

木の左右が片寄ると、 探索に時間がかかってしまう → 片寄らないようにしたい → 平衡二分探索木 二分探索木の問題点 01 赤黒木とは 10

Slide 11

Slide 11 text

ノードの高さが左右で片寄ったら、 回転して片寄りを解消する二分探索木 平衡二分探索木 01 赤黒木とは 11

Slide 12

Slide 12 text

ノードを回転させ、頂点を変更する 木の回転 01 赤黒木とは|回転 左回転 右回転 α

Slide 13

Slide 13 text

01 赤黒木とは もう一度、赤黒木とは ● 平衡二分探索木の一種 ● 主に連想配列(STLコンテナのmapも連想配列)の実装に使われる 13

Slide 14

Slide 14 text

01 赤黒木とは 赤黒木はどうやって片寄りを解消させるか? ● 赤黒木は赤と黒の2色にノードを塗り分ける ● 色分けにはルールがある ● ルールに反する時、色を塗り直し、木を回転させる ルールの説明……の前に 赤黒木のデータ構造を説明する 14

Slide 15

Slide 15 text

各ノードと、それを管理する木のデータがある ● 親ノードへのポインタ ● 左の子ノードへのポインタ ● 右の子ノードへのポインタ ● 値 ● 色(黒 or 赤) 赤黒木のデータ構造 01 赤黒木とは 15 ● 根となるノードのポインタ ● NULL相当のノードのポインタ( NIL) 番兵ノードと呼ばれる 頑張ればNULLでも実装可能 ノード 木

Slide 16

Slide 16 text

赤黒木のルール 目次 02

Slide 17

Slide 17 text

02 赤黒木のルール 5つのルール 1. 各ノードは赤か黒 2. 根は黒 3. 全ての葉(NIL)は黒 4. あるノードが赤なら、その子ノードは黒 5. 各葉と根を結ぶ道は同じ数の黒ノードを持つ 17

Slide 18

Slide 18 text

1. 各ノードは赤か黒 02 赤黒木のルール 18

Slide 19

Slide 19 text

2. 根は黒 02 赤黒木のルール 19

Slide 20

Slide 20 text

3. 全ての葉(NIL)は黒 02 赤黒木のルール 20

Slide 21

Slide 21 text

NGな場合は、色の塗り直し、木の回転が必要 4. あるノードが赤なら、その子ノードは黒 02 赤黒木のルール 21 OK NG

Slide 22

Slide 22 text

5. 各葉と根を結ぶ道は同じ数の黒ノードを持つ 02 赤黒木のルール 22 ルールに反した場合、色の塗り直し、回転が発生する このルールとルール4のおかげで 木の片寄りが最大、2倍で済む 例:右の図  左側は5->3->2->1  右側は5->6

Slide 23

Slide 23 text

赤黒木の操作:挿入 目次 03

Slide 24

Slide 24 text

03 赤黒木の操作:挿入|概要(1/3) 挿入で行うこと 木にノードを追加する 追加するノードの色は赤 0を追加 24

Slide 25

Slide 25 text

03 赤黒木の操作:挿入|概要(2/3) 挿入で行うこと 親ノードの色が赤の場合や、挿入するノードが根の場合、ルールに沿うよう再度色を塗り分ける 1を追加 25 塗り分け

Slide 26

Slide 26 text

03 赤黒木の操作:挿入|概要(3/3) 挿入で行うこと 親ノードの色が赤の場合、再度色を塗り分ける 塗り分け + 回転が発生することもある 2を追加 1を左回転 塗り分け 26

Slide 27

Slide 27 text

03 赤黒木の操作:挿入|流れ 挿入の流れ 1. 挿入する場所を探して、末尾にノードを追加する 2. 色分けを修正する 27

Slide 28

Slide 28 text

03 赤黒木の操作:挿入|ノードの挿入 挿入する場所を探して、末尾にノードを追加する 図は「1」を挿入する場合 挿入する場所が見つからなかった場合(=NIL)は、 挿入するノードが根となる 28

Slide 29

Slide 29 text

03 赤黒木の操作:挿入|色分けの修正 色分けを修正する 挿入するノードは赤色とする 親ノードが赤色だった場合、赤が連続してルールに反するので修正する 修正パターンは3つ × 左右2通り ここでは、左の3パターンのみ紹介 右の場合は、操作の左右を入れ替える 29

Slide 30

Slide 30 text

zを挿入するノードとする 1. 親の親の子(叔父)ノードが赤色 2. 親の親の子(叔父)ノードが黒色 + 挿入するノード(z)が親の左の子 3. 親の親の子(叔父)ノードが黒色 + 挿入するノード(z)が親の右の子 03 赤黒木の操作:挿入|色分けの修正 3つの修正パターン 30

Slide 31

Slide 31 text

03 赤黒木の操作:挿入|色分けの修正 パターン1:叔父ノードが赤色 親、叔父を赤から黒に。祖父を黒から赤にする 祖父の親が赤の可能性があるため、祖父のノードから再度色分けチェックをする このノードか ら色分け再 チェック 31

Slide 32

Slide 32 text

03 赤黒木の操作:挿入|色分けの修正 パターン2:叔父ノードが黒色 + zが親の左の子 祖父ノードを右回転し、親、祖父の色を修正する 右回転 色分け 32

Slide 33

Slide 33 text

03 赤黒木の操作:挿入|色分けの修正 パターン3:叔父ノードが黒色 + zが親の右の子 左回転 親ノードを左回転し、パターン2を適用する パターン2 33

Slide 34

Slide 34 text

赤黒木の操作:削除 目次 04

Slide 35

Slide 35 text

04 赤黒木の操作:削除|流れ ノード削除の流れ 1. ノードの入れ替え 2. 削除される色が黒なら、色分け変更 + 回転 3. ノードをdelete(free) 35

Slide 36

Slide 36 text

04 赤黒木の操作:削除|ノードの入れ替え ノードの入れ替え 36 2. 削除するノードの子供が 2 個の場合 入れ替えは大きく 2パターン。zを削除するノードとする 1. 削除するノードの子供が 0, 1 個の場合

Slide 37

Slide 37 text

04 赤黒木の操作:削除|子が0, 1個の場合の入れ替え 削除するノードの子が0, 1個の場合 37 子とzの親を入れ替える zからは他のノードを辿れるが、他のノードからzに辿れない状態になる

Slide 38

Slide 38 text

1. 削除するノードの、次に大きいノードを探す 2. 削除するノードと、次に大きいノードを入れ替える ● 次に大きいノードの場所によって、2パターンに分岐 3. 次に大きいノードの色を、削除するノードの色に変更する ● 0, 1個の場合と異なり、 削除される色は、次に大きいノードの色 色分け + 回転をする際は、 もともと次に大きいノードがあった位置のノード(x)から 削除による影響がないか見ていく 削除するノードの子が2個の場合 04 赤黒木の操作:削除|子が2個の場合の入れ替え(1/5) 38

Slide 39

Slide 39 text

削除するノードの、 右の子から一番小さいノードを探す 一番小さいノードを探すには、ノードの左をたどる 見つかるノードは ● 削除するノードの子 ● 削除するノードの子のさらなる子孫 のどちらか 04 赤黒木の操作:削除|子が2個の場合の入れ替え(2/5) 39 1. 削除するノードの、次に大きいノードを探す

Slide 40

Slide 40 text

2. 削除するノードと、次に大きいノードを入れ替える 04 赤黒木の操作:削除|子が2個の場合の入れ替え(3/5) 40 zと次を 入替 次に大きいノードが、削除するノードの子の場合 (xは後で色替え + 回転するときに見るノード) 次ノード があった所 にxが入る

Slide 41

Slide 41 text

2. 削除するノードと、次に大きいノードを入れ替える 04 赤黒木の操作:削除|子が2個の場合の入れ替え(4/5) 41 次に大きいノードが、削除するノードの子のさらなる子孫の場合 次とxを 入替 zと次を 入替 次ノード があった所 にxが入る

Slide 42

Slide 42 text

3. 次に大きいノードの色を、削除するノードの色に変更する 04 赤黒木の操作:削除|子が2個の場合の入れ替え(5/5) 42 次に大きいノードの色が黒なら、zの色に変わることで黒が一つ減ってしまう → 色分け + 回転して、葉までの黒の数を合わせる → 「次」ノードがあった所にいる、xから色分け + 回転を見ていく

Slide 43

Slide 43 text

while (xが根でない && xの色が黒) { xの兄弟の色、xの兄弟の子の色に応じて パターン分けして、色分け + 回転 } xの色を黒にする 色分け + 回転の流れ 04 赤黒木の操作:削除|色分け + 回転:流れ(1/3) 43

Slide 44

Slide 44 text

while (xが根でない && xの色が黒) { xの兄弟の色、xの兄弟の子の色に応じて パターン分けして、色分け + 回転 } xの色を黒にする 色分け + 回転の流れ 04 赤黒木の操作:削除|色分け + 回転:流れ(2/3) 44 xが根でない  → 初期状態では起こらない    ループを回って根に到達した際に抜ける xの色が黒  → xの色が赤なら、黒にすれば    黒の数が削除前と同じになる

Slide 45

Slide 45 text

色分け + 回転の流れ 04 赤黒木の操作:削除|色分け + 回転:流れ(3/3) 45 while (xが根でない && xの色が黒) { xの兄弟の色、xの兄弟の子の色に応じて パターン分けして、色分け + 回転 } xの色を黒にする パターンは4つ × 左右2通り (右の場合は反転して考える) 1. 兄弟の色が赤 2. 兄弟の色が黒 + 兄弟の子が左右どちらも黒 3. 兄弟の色が黒 + 兄弟の子の左が赤、右が黒 4. 兄弟の色が黒 + 兄弟の子の右が赤

Slide 46

Slide 46 text

パターン1. 兄弟の色が赤 04 赤黒木の操作:削除|色分け + 回転:各種パターン(1/4) 46 色交換後、親を左回転する。左をxの兄弟として再度ループを回る (木を下っていくイメージ) 親と兄弟の 色を交換 親を左回転 黒の個数 2 3 3 1 3 3 2 3 3

Slide 47

Slide 47 text

パターン2. 兄弟の色が黒 + 兄弟の子が左右どちらも黒 04 赤黒木の操作:削除|色分け + 回転:各種パターン(2/4) 47 兄弟の色を 赤にする 兄弟の色を赤にする。見るノードを親として再度ループを回る (木を登っていくイメージ) 黒の個数 1 2 2 1 1 1

Slide 48

Slide 48 text

色交換後、兄弟を右回転する。左をxの兄弟としてパターン4へ進む パターン3. 兄弟の色が黒 + 兄弟の子の左が赤、右が黒 04 赤黒木の操作:削除|色分け + 回転:各種パターン(3/4) 48 兄弟と左の 色を交換 兄弟を 右回転 黒の個数 1 2 2 2 2 1 1 2 2 2

Slide 49

Slide 49 text

パターン4. 兄弟の色が黒 + 兄弟の子の右が赤 04 赤黒木の操作:削除|色分け + 回転:各種パターン(4/4) 49 各ノードの数が揃うパターン 見るノードを根として、ループを抜ける 親と兄弟の 色を交換 右を黒に 親を左回転 黒の個数 1 or 2 2 or 3 2 or 3 2 or 3 3 or 4 2 2 or 3 2 or 3 2 or 3

Slide 50

Slide 50 text

Q. パターン1で木を下りて、パターン2で木を登る   無限ループにならないか? Q & A 04 赤黒木の操作:削除|色分け + 回転:Q & A(1/4) 50

Slide 51

Slide 51 text

A. ならない パターン1 → パターン2の場合 木を登ってノードの色が赤になり、ループを抜ける Q & A 04 赤黒木の操作:削除|色分け + 回転:Q & A(2/4) 51

Slide 52

Slide 52 text

パターン2の場合 パターン2 → パターン1なら、あとはパターン1通りに進む パターン2 → パターン2は根までループする可能性がある(最大lgN) Q & A 04 赤黒木の操作:削除|色分け + 回転:Q & A(3/4) 52

Slide 53

Slide 53 text

参考:パターン3、パターン4の状態遷移図 Q & A 04 赤黒木の操作:削除|色分け + 回転:Q & A(4/4) 53

Slide 54

Slide 54 text

最後に 目次 05

Slide 55

Slide 55 text

05 最後に(1/2) 赤黒木の実装は 複雑です AVL木など 他の平衡二分探索木の 実装も検討ください 55

Slide 56

Slide 56 text

『アルゴリズムイントロダクション 第3版 第1巻』 ● オススメの読む順番:付録 B.5 木 → 12 2分探索木 → 13 2色木 木 (数学) - Wikipedia ● 木の図を参考にさせていただきました。 Red-black tree deletion: steps + 10 examples - YouTube 参考文献・URL 05 最後に(2/2) 56