logo

グラフの深さ優先検索または DFS

深さ優先トラバーサル (DFS) グラフは次のようになります ツリーの深さ優先トラバース。 ここでの唯一の注意点は、ツリーとは異なり、グラフにはサイクルが含まれる可能性がある (ノードが 2 回訪問される可能性がある) ということです。ノードを複数回処理しないようにするには、ブール値の訪問済み配列を使用します。グラフには複数の DFS トラバーサルを含めることができます。

例:

入力: n = 4、e = 6
0 -> 1、0 -> 2、1 -> 2、2 -> 0、2 -> 3、3 -> 3
出力: 頂点 1 からの DFS : 1 2 0 3
説明:
DFS 図:



例1

例1

入力: n = 4、e = 6
2 -> 0、0 -> 2、1 -> 2、0 -> 1、3 -> 3、1 -> 3
出力: 頂点 2 からの DFS : 2 0 1 3
説明:
DFS 図:

例 2

例 2

グラフの推奨練習 DFS 試してみよう!

DFS はどのように機能しますか?

深さ優先検索は、ツリーまたはグラフのデータ構造を走査または検索するためのアルゴリズムです。アルゴリズムはルート ノード (グラフの場合はルート ノードとして任意のノードを選択) から開始し、バックトラックする前に各ブランチに沿って可能な限り探索します。

の仕組みを理解しましょう 深さ優先検索 次の図を参考にしてください。

ステップ1: 最初はスタックと訪問された配列は空です。

動的プログラミング

スタックおよび訪問された配列は、最初は空です。

ステップ2: 0 を訪問し、まだ訪問されていない隣接ノードをスタックに入れます。

ノード 0 にアクセスし、隣接するノード (1、2、3) をスタックに追加します。

ステップ 3: ここで、ノード 1 がスタックの最上位にあるので、ノード 1 にアクセスしてスタックからポップし、アクセスされていない隣接ノードをすべてスタックに置きます。

ノード 1 にアクセスします

ステップ 4: 今、 ノード 2 はスタックの最上位にあるため、ノード 2 にアクセスしてスタックからポップし、アクセスされていない隣接ノード (つまり 3、4) をすべてスタックに置きます。

ノード 2 を訪問し、未訪問の隣接ノード (3、4) をスタックに追加します。

ステップ5: ここで、ノード 4 がスタックの最上位にあるので、ノード 4 にアクセスしてスタックからポップし、アクセスされていない隣接ノードをすべてスタックに置きます。

ノード 4 にアクセスします

ステップ6: ここで、ノード 3 がスタックの最上位にあるので、ノード 3 にアクセスしてスタックからポップし、アクセスされていない隣接ノードをすべてスタックに置きます。

ノード 3 にアクセスします

これで、スタックが空になり、すべてのノードを訪問し、DFS トラバーサルが終了したことを意味します。

上記のアプローチの実装を以下に示します。

C++

セレンを学ぶ




// C++ program to print DFS traversal from> // a given vertex in a given graph> #include> using> namespace> std;> // Graph class represents a directed graph> // using adjacency list representation> class> Graph {> public>:> >map<>int>,>bool>>訪問しました;>> map<>int>, list<>int>>> 形容詞;>> >// Function to add an edge to graph> >void> addEdge(>int> v,>int> w);> >// DFS traversal of the vertices> >// reachable from v> >void> DFS(>int> v);> };> void> Graph::addEdge(>int> v,>int> w)> {> >// Add w to v’s list.> >adj[v].push_back(w);> }> void> Graph::DFS(>int> v)> {> >// Mark the current node as visited and> >// print it> >visited[v] =>true>;> >cout << v <<>' '>;> >// Recur for all the vertices adjacent> >// to this vertex> >list<>int>>::反復子 i;>> >for> (i = adj[v].begin(); i != adj[v].end(); ++i)> >if> (!visited[*i])> >DFS(*i);> }> // Driver code> int> main()> {> >// Create a graph given in the above diagram> >Graph g;> >g.addEdge(0, 1);> >g.addEdge(0, 2);> >g.addEdge(1, 2);> >g.addEdge(2, 0);> >g.addEdge(2, 3);> >g.addEdge(3, 3);> >cout <<>'Following is Depth First Traversal'> >' (starting from vertex 2) '>;> >// Function call> >g.DFS(2);> >return> 0;> }> // improved by Vishnudev C>

>

>

ジャワ




// Java program to print DFS traversal> // from a given graph> import> java.io.*;> import> java.util.*;> // This class represents a> // directed graph using adjacency> // list representation> class> Graph {> >private> int> V;> >// Array of lists for> >// Adjacency List Representation> >private> LinkedList adj[];> >// Constructor> >@SuppressWarnings>(>'unchecked'>) Graph(>int> v)> >{> >V = v;> >adj =>new> LinkedList[v];> >for> (>int> i =>0>; i adj[i] = new LinkedList(); } // Function to add an edge into the graph void addEdge(int v, int w) { // Add w to v's list. adj[v].add(w); } // A function used by DFS void DFSUtil(int v, boolean visited[]) { // Mark the current node as visited and print it visited[v] = true; System.out.print(v + ' '); // Recur for all the vertices adjacent to this // vertex Iterator i = adj[v].listIterator(); while (i.hasNext()) { int n = i.next(); if (!visited[n]) DFSUtil(n, visited); } } // The function to do DFS traversal. // It uses recursive DFSUtil() void DFS(int v) { // Mark all the vertices as // not visited(set as // false by default in java) boolean visited[] = new boolean[V]; // Call the recursive helper // function to print DFS // traversal DFSUtil(v, visited); } // Driver Code public static void main(String args[]) { Graph g = new Graph(4); g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 2); g.addEdge(2, 0); g.addEdge(2, 3); g.addEdge(3, 3); System.out.println( 'Following is Depth First Traversal ' + '(starting from vertex 2)'); // Function call g.DFS(2); } } // This code is contributed by Aakash Hasija>

>

カプセル化Java

>

Python3


Javaで配列を初期化する



# Python3 program to print DFS traversal> # from a given graph> from> collections>import> defaultdict> # This class represents a directed graph using> # adjacency list representation> class> Graph:> ># Constructor> >def> __init__(>self>):> ># Default dictionary to store graph> >self>.graph>=> defaultdict(>list>)> > ># Function to add an edge to graph> >def> addEdge(>self>, u, v):> >self>.graph[u].append(v)> > ># A function used by DFS> >def> DFSUtil(>self>, v, visited):> ># Mark the current node as visited> ># and print it> >visited.add(v)> >print>(v, end>=>' '>)> ># Recur for all the vertices> ># adjacent to this vertex> >for> neighbour>in> self>.graph[v]:> >if> neighbour>not> in> visited:> >self>.DFSUtil(neighbour, visited)> > ># The function to do DFS traversal. It uses> ># recursive DFSUtil()> >def> DFS(>self>, v):> ># Create a set to store visited vertices> >visited>=> set>()> ># Call the recursive helper function> ># to print DFS traversal> >self>.DFSUtil(v, visited)> # Driver's code> if> __name__>=>=> '__main__'>:> >g>=> Graph()> >g.addEdge(>0>,>1>)> >g.addEdge(>0>,>2>)> >g.addEdge(>1>,>2>)> >g.addEdge(>2>,>0>)> >g.addEdge(>2>,>3>)> >g.addEdge(>3>,>3>)> >print>(>'Following is Depth First Traversal (starting from vertex 2)'>)> > ># Function call> >g.DFS(>2>)> # This code is contributed by Neelam Yadav>

>

>

C#




// C# program to print DFS traversal> // from a given graph> using> System;> using> System.Collections.Generic;> // This class represents a directed graph> // using adjacency list representation> class> Graph {> >private> int> V;> >// Array of lists for> >// Adjacency List Representation> >private> List<>int>>[] adj;>>' // Constructor> >Graph(>int> v)> >{> >V = v;> >adj =>new> List<>int>>[ で ];>> for> (>int> i = 0; i adj[i] = new List (); } // グラフにエッジを追加する関数 void AddEdge(int v, int w) { // v のリストに w を追加します。 adj[v].Add(w); } // DFS によって使用される関数 void DFSUtil(int v, bool[] Visited) { // 現在のノードを訪問済みとしてマークし、 // それを出力します Visited[v] = true; Console.Write(v + ' '); // すべての頂点に対して繰り返します // この頂点リストに隣接します vList = adj[v]; foreach(vList の var n) { if (!visited[n]) DFSUtil(n, Visited); } } // DFS トラバーサルを行う関数。 // 再帰的な DFSUtil() を使用します void DFS(int v) { // すべての頂点を未訪問としてマークします // (C# ではデフォルトで false に設定されます) bool[] Visited = new bool[V]; // 再帰ヘルパー関数を呼び出して // DFS トラバーサルを出力します DFSUtil(v, Visited); } // ドライバーコード public static void Main(String[] args) { Graph g = new Graph(4); g.AddEdge(0, 1); g.AddEdge(0, 2); g.AddEdge(1, 2); g.AddEdge(2, 0); g.AddEdge(2, 3); g.AddEdge(3, 3); Console.WriteLine( '以下は深さ優先トラバーサルです ' + '(頂点 2 から開始)'); // 関数呼び出し g.DFS(2); Console.ReadKey(); } } // このコードは techno2mahi によって提供されています>>'

> 




// Javascript program to print DFS> // traversal from a given> // graph> // This class represents a> // directed graph using adjacency> // list representation> class Graph> {> > >// Constructor> >constructor(v)> >{> >this>.V = v;> >this>.adj =>new> Array(v);> >for>(let i = 0; i this.adj[i] = []; } // Function to add an edge into the graph addEdge(v, w) { // Add w to v's list. this.adj[v].push(w); } // A function used by DFS DFSUtil(v, visited) { // Mark the current node as visited and print it visited[v] = true; console.log(v + ' '); // Recur for all the vertices adjacent to this // vertex for(let i of this.adj[v].values()) { let n = i if (!visited[n]) this.DFSUtil(n, visited); } } // The function to do DFS traversal. // It uses recursive // DFSUtil() DFS(v) { // Mark all the vertices as // not visited(set as // false by default in java) let visited = new Array(this.V); for(let i = 0; i

>

>

出力

Following is Depth First Traversal (starting from vertex 2) 2 0 1 3>

深さ優先検索の複雑さの分析:

  • 時間計算量: O(V + E)。ここで、V はグラフ内の頂点の数、E はエッジの数です。
  • 補助スペース: O(V + E)、サイズ V の追加の訪問配列が必要になるため、DFS 関数の反復呼び出しのスタック サイズになります。