DFS(Depth First Search):A simple algorithm for traversing a graph.
Features: Starting from a distinguished source vertex, DFS will traverse the graph-first'. Everytime DFS hits a branching point(a vertex with more than one neighbors), DFS will choose one of the unvisited neighbors and visit this neighbor vertex. DFS repeats this process and goes deeper until it reaches a vertex where it cannot go any deeper. When this happens, DFS will "backtrack" and explore another unvisited neighbor(s), if any.
Implementation:
-Idea: Recursion
import java.io.*;
import java.util.*;
public class Graph {
private int V; //number of vertices
private LinkedList<Integer> adj[]; //Array of lists for Adjacency List Representation
//Constructor
Graph(int v) {
V = v;
adj = new LinkedList[v];
for (int i = 0; i < v; ++i) {
adj[i] = new LinkedList();
}
}
//The function to add edge into the graph
void addEdge(int v, int w) {
adj[v].add(w); //Add w to v's list (v is a vertice)
}
//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.println(v + " ");
//Recur for all the vertices adjacent to this vetex
Iterator<Integer> i = adj[v].listIterator();
while (i.hasNext()) {
int n = i.next();
if (!visited[n]) DFSUtil(n, visited);
}
}
void DFS(int v) {
//Mark all the vertices as not visited
boolean visited[] = new boolean[V]; //just use one-D array to indicate whether this vertex has been visited
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);
g.DFS(2);
}
}
Note: we use an array of linkedlist to represent a graph, with each index of the array as a vertex in the graph and the value of that index as a list of vertices that connect to the specific index. We also use one D boolean array with size n to indicate whether a specific vertice has been accessed.
Comparison with recursive backtracking: Backtracking (automatically) un-flag visited vertices (reset the state to the previous state) when the recursion backtracks to allow re-visitation of those vertices from another branch. For DFS, it flags each visited vertice so that each vertice will not be visited twice.
Application:
1. 找连通块
2. Test the connectivity of a graph (Uva 592)
A. 找连通块实现:
class ConnectivityDFS {
boolean[][] graph;
int[][] index;
int count;
public ConnectivityDFS(int row, int col) {
count = 0;
index = new int[row][col];
graph = new boolean[row][col];
}
public void fillGraph(boolean[][] g) {
for (int i = 0; i < g.length; i++) {
for (int j = 0; j < g[0].length; j++) {
graph[i][j] = g[i][j];
}
}
}
public void dfs(int r, int c) {
if (r < 0 || r >= graph.length || c < 0 || c >= graph[0].length) return;
if (graph[r][c] != true || index[r][c] != 0) return;
index[r][c] = count;
for (int dr = -1; dr < 1; dr++) {
for (int dc = -1; dc < 1; dc++) {
dfs(r + dr, c + dc);
}
}
}
public static void main(String args[]) {
ConnectivityDFS d = new ConnectivityDFS(3, 3);
boolean[][] g = {{true, true, false}, {true, false, true}, {false, false, false}};
d.fillGraph(g);
for (int i = 0; i < g.length; i++) {
for (int j = 0; j < g[0].length; j++) {
if (d.index[i][j] == 0 && d.graph[i][j] == true) {
d.count++;
d.dfs(i, j);
}
}
}
System.out.println(d.count);
}
Efficiency:
Using Adjacency List: O(V + E), where V is the number of vertices and E is the number of edges
Using Adjacency Matrix: O(n^2), where n is the dimension of the matrix