• 検索結果がありません。

アルゴリズムとデータ構造

N/A
N/A
Protected

Academic year: 2021

シェア "アルゴリズムとデータ構造"

Copied!
15
0
0

読み込み中.... (全文を見る)

全文

(1)

アルゴリズムとデータ構造

2012 年 7 月 12 日

酒居敬一 ([email protected])

http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/ALG/2012/index.html

1

(2)

各種の連結性の判定

(249ページ)

•   連結の強さを表現する概念

•   無向グラフ

–   二重連結

–   二重連結成分

•   有向グラフ

–   強連結

–   強連結成分

2

(3)

H I

図4 . 4 . 1 二重連結グラフ

図4 . 4 . 2 関節点と二重連結成分

二重連結

(250ページ)

グラフから1つの頂点と その頂点を端点とする

すべての辺を除いて得られる グラフを考えたとき、どの頂点を 除いた場合でもグラフが連結 グラフであるとき、元のグラフは 二重連結であるという。

C B E

•  二重連結成分とは、二重  連結な部分グラフのこと。

•  取り除くと非連結になる

 頂点を関節点という。 3

(4)

関節点検出のアルゴリズム

(251ページ)

•   前提条件

–   関節点が検出されなければ、二重連結。

–   深さ優先探索の結果の木を仮定して、

子孫・祖先・部分木という言葉を使う。

•   場合分け

–   頂点が木の根の場合

•   子が2個以上ならその頂点は関節点である。

–   頂点が木の根ではない場合(次のページ)

•   着目する3頂点の位置で2つに場合分けする。

–  いずれもAB間・BC間・CA間の道について考える。 4

(5)

A B

BはAの祖先、CはAの子孫、

という位置関係の場合。

(図 4 . 4 . 3 a)

•  もしAが関節点ならば、

以下の2つは同じことを言っている 1.   BC間の道が必ずAを通ること

2.   Cを含む部分木の中にAの祖先への 逆辺がないこと

•  図のように逆辺 (点線で表示)があれば、

 Aを経由せずにBC間を移動できるので、

 この場合はAは関節点ではない。

5

(6)

BはAの子孫、CもAの子孫、

という位置関係の場合。

(図 4 . 4 . 3 b)

•  図のように、BとCの双方が、Aの祖先と  Aを経由せずに連絡できれば、Aは

関節点ではない。この場合、Aを経由 せずにBとCが連絡できる。

•  BとCがAを通らないと連絡できない  のは、どちらかの部分木にAより上の  祖先を指す逆辺がないからであり、

 Aが関節点になっている。

6

(7)

public class Biconnected<E> { private int sequence;

private int visit(Node<E> node){

node.setSequence(++this.sequence);

int min = this.sequence;

for(Node<E> neighbor: node.getEdges()){

if(neighbor.getSequence() == 0){

int m = visit(neighbor);

min = Math.min(min, m);

boolean artic;

if (node.getSequence() == 1) {

artic = (neighbor.getSequence() != 2);

} else {

artic = (m >= node.getSequence());

}

if(artic) System.out.println("

頂点

" + node.getValue() + "

は関節点

");

} else if (neighbor.getSequence() < min){

min = neighbor.getSequence();

} }

return min;

}

public void search(Node<E> start){

this.sequence = 0;

visit(start);

}

} 7

根の子が2個以上(順序数が2より大きい)

ときは、根が関節点。

隣接する未訪問の頂点に関しては、

深さ優先探索なので探索する。

その結果、訪問順が付けられる。

自分(node)の子から、祖先への逆辺 がなければ、自分は関節点。

隣接する訪問済みの頂点に関しては、

より祖先へ向かう辺(逆辺含む)の先の 頂点の順序数を保持する。

深く探索していく過程で、より祖先寄りの祖先への逆辺を

調べながら進んでいる。

(8)

public static void main(String[] args) { System.out.println("

4.4.2");

for(Node<Character> node: test_data2){

node.reset();

}

nodeA.connect(nodeC);

nodeA.connect(nodeD);

nodeB.connect(nodeC);

nodeB.connect(nodeD);

nodeC.connect(nodeE);

nodeD.connect(nodeF);

nodeD.connect(nodeG);

nodeF.connect(nodeG);

nodeE.connect(nodeH);

nodeE.connect(nodeI);

new Biconnected<Character>().search(nodeA);

}

8

図4.4.2

頂点Dは関節点 頂点Eは関節点 頂点Eは関節点 頂点Cは関節点

H I

C B E

(9)

図4 . 4 . 5 強連結グラフ

図4 . 4 . 6 強連結成分への分割

強連結

(255ページ)

有向グラフの各頂点から任意の 頂点へ至る道が存在するとき、

この有向グラフを強連結であるという。

部分グラフのうち、強連結であって、

しかもそれ以上頂点を追加すると

強連結でなくなるものを強連結成分という。

9

(10)

強連結成分への分割アルゴリズム

(256ページ)

ü  有向グラフの深さ優先探索の応用である。

ü  下降辺は強連結性に貢献しない。

ü  下降辺の両端の頂点について、祖先から子孫へ 木の辺から成る道がすでに存在する。

ü  上昇辺の両端の頂点は同じ強連結成分に属す。

ü  木の辺と上昇辺で閉路を作る。

ü  木の辺で下降し、上昇辺で上昇して元に戻れる。

ü  交差辺は、単純ではない。

ü  強連結成分に属す・属さないの2種類がある。

10

(11)

図4 . 4 . 7 深さ優先探索の木と強連結成分の関係

(木の辺だけを見たときは木)

•  深さ優先探索の木の上で強連結成分を表す。

•  実際は下降辺・上昇辺・交差辺も存在してて、

 それらとともに強連結成分を作っている。

•  各強連結成分に最初に訪問した頂点   =その部分木の根。

•  部分木の根からその子孫に到達可能。

•  部分木が強連結成分なら、

 木の辺を0回以上通った後で

 上昇辺か交差辺を通って根に戻れる。

•  深さ優先探索の木の葉から、上昇辺  や交差辺を通ってその葉の祖先に  たどり着くことができ、そういう祖先の  うちで最も根に近いものを求める。

•  教科書の lowlink 変数

強連結成分を見つけたら、

この辺を木からはずす。 11

(12)

public class StrongComponent<E> { private int sequence;

private Stack<Node<E>> stack = new Stack<Node<E>>();

private int visit(Node<E> node){

node.setSequence(++this.sequence);

int min = this.sequence;

stack.push(node);

for(Node<E> neighbor: node.getEdges()){

int m;

if(neighbor.getSequence() == 0) m = visit(neighbor);

else m = neighbor.getSequence();

min = Math.min(min, m);

}

if(min == node.getSequence()){

Node<E> component;

do {

component = stack.pop();

System.out.print(component.getValue() + " ");

component.setSequence(Integer.MAX_VALUE);

} while (component != node);

System.out.println();

}

return min;

}

public void search(Collection<Node<E>> graph){

this.sequence = 0; this.stack.clear();

for(Node<E> node: graph) if(node.getSequence() == 0) visit(node);

}}

12

訪問順seq

この根からつながる

強連結成分を取り出す。

隣の頂点が訪問済みの場合は、

そこからたどれる最も根に

近い頂点の訪問順を更新する。

訪問済みなので木の辺じゃない。

未訪問の場合は探索を進める。

深さ優先探索し終わった後、

調べてみたら、

強連結成分の根だった

(seq=lowlink)

教科書のlowlink

交差辺経由で探索されないようにする。

(13)

public static void main(String[] args) { System.out.println("

4.4.9");

for(Node<Character> node: test_data2){

node.reset();

}

nodeA.connectTo(nodeB);

nodeA.connectTo(nodeC);

nodeB.connectTo(nodeE);

nodeB.connectTo(nodeF);

nodeC.connectTo(nodeF);

nodeC.connectTo(nodeG);

nodeD.connectTo(nodeA);

nodeE.connectTo(nodeD);

nodeE.connectTo(nodeH);

nodeF.connectTo(nodeE);

nodeG.connectTo(nodeH);

nodeH.connectTo(nodeI);

nodeI.connectTo(nodeH);

new StrongComponent<Character>().search(test_data2);

}

13

図4.4.9 I H G

C F D E B A

図 4 . 4 . 9 プログラムの実行例

(実線は木の辺、点線はそれ以外の辺)

(14)

擬似コード

(Pseudocode)

•   擬似プログラムともいう。

•   アルゴリズムを既存のプログラミング言語に 似せて書いたもの。

–   かつてはPascalやFortran、今はJava?

•   要点だけ書くのでそのまま動く保障はない。

–   教科書のコードはかなり完成度が高い。

–   Java だと、どこでも動くコードを書きやすい。

14

(15)

期末試験


•   教室 : C101 (いつものA107は使えません)

•   日時 : 2012年7月30日16時30分〜18時00分

–   入室限度 : 16時50分まで –   退出可能 : 17時00分より

•   持ち込み可

–   教科書・資料 ( 自筆・コピー問わず ) は持ち込み可 –   人間・パソコン・携帯電話・ PHS など持ち込み不可

•   学生証必携

–   持っていない場合は教務で発行してもらうこと

15

参照

関連したドキュメント

子どもたちが自由に遊ぶことのでき るエリア。UNOICHIを通して、大人 だけでなく子どもにも宇野港の魅力

断するだけではなく︑遺言者の真意を探求すべきものであ

 今日のセミナーは、人生の最終ステージまで芸術の力 でイキイキと生き抜くことができる社会をどのようにつ

先ほどの事前の御意見のところでもいろいろな施策の要求、施策が必要で、それに対して財

きも活発になってきております。そういう意味では、このカーボン・プライシングとい

自然言語というのは、生得 な文法 があるということです。 生まれつき に、人 に わっている 力を って乳幼児が獲得できる言語だという え です。 語の それ自 も、 から

・私は小さい頃は人見知りの激しい子どもでした。しかし、当時の担任の先生が遊びを

現を教えても らい活用 したところ 、その子は すぐ動いた 。そういっ たことで非常 に役に立 っ た と い う 声 も いた だ い てい ま す 。 1 回の 派 遣 でも 十 分 だ っ た、 そ