210 likes | 355 Views
07. 木. 五島. 木 とは. 循環 / 非循環グラフ. 森. 木 (tree) : 連結な森,森の連結成分 { 木 } ⊂ { 森 } 森は木の集合. 循環 / 非循環グラフの例. 非循環グラフ. 循環グラフ. 木. 木. 無向循環グラフ. DAG. DAG. DAG. 有向循環グラフ. 根 (root). (連結非循環グラフの)根 (root) : 頂点を 1 つ選んで, それが一番「上」にあると考える 木(無向): どの頂点も根になり得る 根付き木 (rooted tree) DAG (有向):
E N D
離散数学 07. 木 五島
離散数学 木 とは
離散数学 循環 / 非循環グラフ 森 • 木 (tree): • 連結な森,森の連結成分 • {木} ⊂ {森} • 森は木の集合
離散数学 循環 / 非循環グラフの例 非循環グラフ 循環グラフ 木 木 無向循環グラフ DAG DAG DAG 有向循環グラフ
離散数学 根 (root) • (連結非循環グラフの)根 (root): • 頂点を1つ選んで,それが一番「上」にあると考える • 木(無向): • どの頂点も根になり得る • 根付き木 (rooted tree) • DAG(有向): • 根がない場合もある どれが根? 根のない DAG
離散数学 木の性質
「木」のイメージ: • 「根があって,枝分かれして,葉に至る」 • 「木」=木(無向非循環グラフ)? • 「木」 ⇒ 木(無向非循環グラフ) • 「木」なら,枝分かれした先で合流しない ⇒ 非循環 • 木(無向非循環グラフ) ⇒ 「木」 • 任意の頂点を根とみなすことができる • 木なので,循環はない • 連結なので,根からすべての頂点に到達可能 離散数学 「木」 と 木(無向非循環グラフ) どれが根?
任意の2頂点 x,yを結ぶ道はただ 1つ • (辺の個数) = (頂点の個数) − 1 • (頂点数が2以上なら)少なくとも 2個の端末点がある • 端末点: 次数 1 の頂点 • 頂点 −−,++ • −−: 頂点数 nの木から端末点を1つ除去すると,頂点数 n − 1 の木になる. • ++:頂点数 nの木に,頂点1つ(とこれらを接続する辺を1つ)を加えると,頂点数 n + 1 の木になる. 離散数学 木 の 性質
任意の2頂点 x,yを結ぶ道はただ 1つ • 2つあれば,閉路 離散数学 木 の 性質(証明 1/5)
離散数学 木 の 性質(証明 2/5) • −−: 頂点数 nの木から端末点を1つ除去すると,頂点数 n − 1 の木になる. • 頂点を除去して閉路ができることはない. • 端末点なので,除去しても非連結にはならない.
離散数学 木 の 性質(証明 3/5) • ++:頂点数 nの木に,頂点を1つと,これらを接続する辺を1つ加えると,頂点数 n + 1 の木になる. • 頂点 1つと辺 1つを加えて閉路を作ることはできない.
離散数学 木 の 性質(証明 4/5) • 頂点数 ++ の繰り返しによって,任意の木を構築することができる. • 任意の木から,頂点数 −− を繰り返して頂点数 1 のグラフを得る. • 頂点数 ++ を −− とは逆に繰り得返して元(任意の木)に戻せる. 4 3 1 2 2 1 3 4
(頂点数が2以上なら)少なくとも2個の端末点がある(頂点数が2以上なら)少なくとも2個の端末点がある • 頂点数2 の木には,2個の端末点がある. • 頂点 ++ すると… • 端末点につなぐと,1つ減って 1つ増える. • 非端末点につなぐと,1つ増える. • (辺の数) = (頂点の数) − 1 • 頂点数2の木では,辺の数は 1,頂点の数は 2. • 頂点 ++ すると,1ずつ増える. 離散数学 木 の 性質(証明 5/5) 1 2 3 4
離散数学 木の巡回
離散数学 visit() class Graph {private:/* … */int left(int u);int right(int u);public:void visit(int u);}; void Graph::visit (int u) {if (left(u)) visit(left(u));if (right(u))visit(right(u));} u の左の子の頂点の番号u の右の子の頂点の番号visit() の宣言 u: 頂点の番号 (>0)u に左の子があれば,訪れるu に右の子があれば,訪れる
離散数学 再帰呼び出しによる二分木の巡回 call call visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } return visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } c b a d e
離散数学 再帰呼び出しによる二分木の巡回 行きがけ: call 直後 call visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } return 帰りがけ: return 直前 visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } 行きがけ c left b a d 帰りがけ e right
木の巡回順序: 頂点の処理順序 • 行きがけ順 (pre-order) • 通りがけ順 (in-order) (二分木のみ) • 帰りがけ順 (post-order) • 頂点を訪れる (visit) 順番は変わらない が, • 頂点を処理する順番が変わる • 処理: コードでは頂点番号の表示 (print). 離散数学 巡回の順序
離散数学 二分木の巡回 (binary tree traversal) 行きがけ順 (pre-order) 通りがけ順 (in-order) 帰りがけ順 (post-order) visit (int u) { print u; if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); } visit (int u) { if (left(u)) visit(left(u)); print u; if (right(u)) visit(right(u)); } visit (int u) { if (left(u)) visit(left(u)); if (right(u)) visit(right(u)); print u; } c c c left b b b d d d a a a f f f e e e right g g g > abcdefg > cbdafeg > cdbfgea
離散数学 木の巡回 (tree traversal) 行きがけ順 (pre-order) 帰りがけ順 (post-order) visit (int u) { print u; foreach (v in adjacent(u)) visit(v); } visit (int u) { foreach (v in adjacent(u)) visit(v); print u; } 3 1 2 4 4 2 5 3 1 9 7 5 6 8 8 6 9 7
グラフの探索 • 木の巡回の先 • pre-order と post-order の理解が必要 離散数学 次回の内容