アルゴリズムと データ構造 第14回 木構造 木構造 木 階層的な関係を表現するデータ構造 ノード(節)を枝で結んだ構造 木構造 木 根(root) 最も上流のノード 1つの木には1つのみ存在 葉(leaf)・終端節・外部節 最下流のノード 非終端節・内部節 葉以外のノード 木構造 木 子(child) あるノードから見て下流側のノード いくつでも持てる 最下流の葉は子を持たない 親(parent) あるノードから見て上流側のノード 各ノードごとに1つのみ 根には親はなし 木構造 木 兄弟(sibling) 共通の親を持つノード 先祖(ancestor) あるノードから上流側にたどれる全てのノード 子孫(descendant) あるノードから下流側にたどれる全てのノード 木構造 木 レベル(level) 親からどれくらい離れているかを示す 親がレベル0 度数(degree) 各ノードが持つ子の数 すべてのノードの度数がn以下である木:n進木 木構造 木 高さ(height) 葉のレベルの最大値 部分木(subtree) あるノードを根とし、その子孫で構成される木 空目(null tree) ノードや枝がまったく存在しない木 木構造 木 ノード レベル0 葉 レベル1 部分木 枝 X 葉 葉 根 葉 葉 葉 葉 葉 レベル2 レベル3 木構造 順序木と無順序木 兄弟関係にあるノードに 順序関係を有する:順序木 順序関係を有しない:無順序木 X Y 順序木としては違う木 ・ YとZの位置が逆 X Z Z Y 無順序木としては同じ木 ・ 全ノードの要素・親子関係が同じ 木構造 順序木の探索 横型探索(幅優先順探索) レベルの低い点から開始、左から右へ順次探索 終わると次のレベルへ 縦型探索(深さ優先順探索) まず葉に到達するまで枝を下るのを優先して探索 葉に到達したら1つ親に戻って次のノードへ 木構造 木の探索 縦型探索の種類 行きがけ順 通りがけ順 ノードに立ち寄る→左部分木をなぞる→右部分木をなぞる 左部分木をなぞる→ノードに立ち寄る→右部分木をなぞる 帰りがけ順 左部分木をなぞる→右部分木をなぞる→ノードに立ち寄る 木構造 木の探索 横型探索 A B C D E H A B I C D F J E F K G G L H I J K L 木構造 木の探索 縦型探索:行きがけ順 A B C D E H A B I D H F J E I K J G L C F K L G 木構造 木の探索 縦型探索:通りがけ順 A B C D E H H D I B I F J E J K A G L K F L C G 木構造 木の探索 縦型探索:帰りがけ順 A B C D E H H D I I J F J E B G K K L L F G C A 2分木と2分探索木 2分木 木上のノードが左の子と右の子を持つ木 左右の子が区別される:2進木ではない 左の子、右の子のいずれか、または両方ともなくても可 部分木 左の子を根とする部分木:左部分木 右の子を根とする部分木:右部分木 2分木と2分探索木 完全2分木 根から下方レベルへ、かつ同一レベル内では左か ら右へ、ノードが空くことなく詰まっている2分木 最下流でないレベルは全ノードが詰まる 最下流レベルでは左側から詰まる 途中まででもよい 横型探索の走査順を配列の添え字に対応可能 ヒープソートなどで利用 2分木と2分探索木 2分探索木 すべてのノードで その左部分木のノードのキー値が、そのキー値より小 その右部分木のノードのキー値が、そのキー値より大 となっている2分木 通りがけ順でなぞると、昇順で値が得られる 2分木と2分探索木 2分探索木 10 5 15 4 7 1 1 4 6 5 6 12 9 7 9 11 10 20 14 11 12 14 15 20 2分木と2分探索木 2分探索木の実現 typedef struct __bnode { Member data; struct __bnode *left; struct __bnode *right; } BinNode; /* データを格納する構造体 */ /* 左子ノードへのポインタ */ /* 右子ノードへのポインタ */ ・ 子ノードがない場合、left、rightはNULL ・ データ中どれか1つをキー値として定める必要あり 2分木と2分探索木 2分探索木の実現 ノードの探索 根から探索、探索するキー値と各ノードのキー値を比較 探索するキー値の方が小さければ左子ノードと比較 探索するキー値の方が大きければ右子ノードと比較 順次子ノードを探索 見つかれば探索成功 見つからずに葉に到達したら探索失敗 2分木と2分探索木 2分探索木の実現 ノードの探索:3を探索 5 2 7 1 4 3 3の方が大きい:右へ 3の方が小さい:左へ 3と一致:探索成功 2分木と2分探索木 2分探索木の実現 ノードの探索:8を探索 5 2 7 1 4 3 8の方が大きい:右へ 子ノードなし:探索失敗 2分木と2分探索木 2分探索木の実現 ノードの探索の実装 左右子ノードの探索に再帰を利用 探索するキー値とノードのキー値を比較 探索するキー値の方が小さければ左子ノードを再帰探索 探索するキー値の方が大きければ右子ノードを再帰探索 自身がNULLなら子ノードなしなので探索失敗 2分木と2分探索木 2分探索木の実現 ノードの挿入 まず、挿入すべきデータと同じキー値を持つノードがあ るか探索 すでに同じキー値を持つノードがあったら挿入中止 探索失敗箇所にノードを新たに作成し、データ挿入 2分木と2分探索木 2分探索木の実現 ノードの挿入:1を挿入 ノードの挿入:5を挿入 ノードの挿入:9を挿入 ノードの挿入:3を挿入 6 2 7 1 4 3 9 5 1の方が小さい:左へ ノードなし:ここへ追加 5の方が小さい:左へ 3の方が小さい:左へ 9の方が大きい:右へ 5の方が大きい:右へ 3の方が大きい:右へ 2分木と2分探索木 2分探索木の実現 ノードの挿入の実装 ノードの探索と類似:再帰を利用 挿入するデータのキー値とノードのキー値を比較 一致したら挿入中止 挿入するデータのキー値の方が小さければ左子ノードに 再帰挿入処理 挿入するデータのキー値の方が大きければ右子ノードに 再帰挿入処理 自身がNULLなら挿入場所なので挿入 2分木と2分探索木 2分探索木の実現 ノードの削除 3通りのケースで場合分け 子ノードを持たないノードの削除 1つだけ子ノードを持つノードの削除 2つの子ノードを持つノードの削除 2分木と2分探索木 2分探索木の実現 子ノードを持たないノードの削除 該当ノードの親ノードが子を持たないようにする 削除ノードが親ノードの左の子:親の左ポインタNULL 削除ノードが親ノードの右の子:親の右ポインタNULL 2分木と2分探索木 2分探索木の実現 1つだけ子ノードを持つノードの削除 削除するノードの位置に子ノードが配置されるように、ポ インタを付け替え 削除ノードが親ノードの左の子:親ノードの左ポインタが削除 ノードの子をさすよう設定 削除ノードが親ノードの右の子:親ノードの右ポインタが削除 ノードの子をさすよう設定 2分木と2分探索木 2分探索木の実現 2つの子ノードを持つノードの削除 削除ノードの左部分木の中で最大キー値を持つノード が、削除位置に来るようにポインタを付け替え 1. 2. 3. 削除ノードの左部分木からキー値が最大のノードを探索 探索したノードを削除位置に移動 移動前にあった探索ノードを削除 2分木と2分探索木 2分探索木の実現 全ノードの表示 通りがけ順で表示することで昇順に表示 全ノードの表示の実装 1. 2. 3. 左子ノードを再帰的に表示 自身のノードを表示 右子ノードを再帰的に表示 2分木と2分探索木 2分探索木の実現 全ノードの削除 帰りがけ順で各ノードを削除 さもないと子ノードを削除する前に親ノードが消滅 全ノードの削除の実装 1. 2. 3. 左子ノードを再帰的に削除 右子ノードを再帰的に削除 自身のノードを削除
© Copyright 2025 ExpyDoc