さて、これは私がしばらく読んでいるStack Overflowに関する私の最初の投稿であり、このサイトを本当に賞賛しています。これが受け入れられるものになることを願っています。ですから、私はアルゴリズム入門(Cormen。MIT Press)をずっと読んでいて、グラフアルゴリズムに取り組んでいます。私は、幅と深さ優先探索のためにレイアウトされた正式なアルゴリズムを非常に詳細に研究してきました。
深さ優先探索用に指定された疑似コードは次のとおりです。
DFS(G)
-----------------------------------------------------------------------------------
1 for each vertex u ∈ G.V
2 u.color ← WHITE // paint all vertices white; undiscovered
3 u.π ← NIL
4 time ← 0 // global variable, timestamps
5 for each vertex u ∈ G.V
6 if u.color = WHITE
7 DFS-VISIT(G,u)
DFS-VISIT(G, u)
-----------------------------------------------------------------------------------
1 u.color ← GRAY // grey u; it is discovered
2 time ← time + 1
3 u.d ← time
4 for each v ∈ G.Adj[u] // explore edge (u,v)
5 if v.color == WHITE
6 v.π ← u
7 DFS-VISIT(G,v)
8 u.color ← BLACK // blacken u; it is finished
9 time ← time + 1
10 u.f ← time
このアルゴリズムは再帰的であり、複数のソースから進行します(接続されていないグラフのすべての頂点を検出します)。これには、ほとんどの言語固有の実装で省略される可能性のあるいくつかのプロパティがあります。頂点の3つの異なる「色」を区別します。最初はすべてを白で塗りつぶし、次に「発見」されると(DFS-VISITでアクセス)、灰色で塗りつぶされます。DFS-VISITアルゴリズムは、現在の頂点の隣接リストで自分自身を再帰的に呼び出すループを実行し、白いノードへのエッジがなくなったときにのみ頂点を黒く塗りつぶします。
また、各頂点の他の2つの属性は維持されます。udとufは、頂点が検出されたとき(灰色に塗られた)または頂点が終了したとき(黒に塗られた)までのタイムスタンプです。ノードが最初にペイントされるとき、そのノードには1のタイムスタンプがあり、別のノードがペイントされるたびに(灰色か黒か)、次の整数値にインクリメントされます。u.πも維持されます。これは、uが検出されたノードへの単なるポインタです。
Algorithm Non-Recursive-DFS(G)
-----------------------------------------------------------------------------------
1 for each vertex u ∈ G.V
2 u.color ← WHITE
3 u.π ← NIL
4 time = 0
5 for each vertex u ∈ G.V
6 if u.color = WHITE
7 u.color ← GRAY
8 time ← time + 1
9 u.d ← time
7 push(u, S)
8 while stack S not empty
9 u ← pop(S)
10 for each vertex v ∈ G.Adj[u]
11 if v.color = WHITE
12 v.color = GRAY
13 time ← time + 1
14 v.d ← time
15 v.π ← u
16 push(v, S)
17 u.color ← BLACK
18 time ← time + 1
19 u.f ← time
* EDIT 10/31/12 *これは、私のアルゴリズムが長い間正しくないことを恥ずかしく思います。ほとんどの場合は機能しますが、すべてではありません。質問に対して人気のある質問バッジを取得しました。Irfyが以下の回答で問題を見つけた場所を確認したので、そこにクレジットが表示されます。将来これを必要とする人のために、ここで修正しています。
上記のアルゴリズムに欠陥がある人はいますか?私はグラフ理論の専門家ではありませんが、再帰と反復についてはかなりよく理解していると思います。これも同じように機能するはずです。私はそれを再帰的アルゴリズムと機能的に同等にすることを目指しています。必要がない場合でも、最初のアルゴリズムのすべての属性を維持する必要があります。
私がそれを書き始めたとき、私は私が三重のループを持っているとは思いませんでした、しかしそれはそれが判明した方法です。Googleを見回したときに、二重にネストされたループしかない他の反復アルゴリズムを見たことがありますが、それらは複数のソースから進んでいるようには見えません。(つまり、接続されていないグラフのすべての頂点を検出するわけではありません)