Understanding depth first search (DFS)

    In this tutorial, you will learn about the depth-first search algorithm through examples and pseudo-code. In addition, you will learn to implement DFS in C.
    Depth-first search or depth-first traversal is a recursive algorithm used to search all vertices of a graph or tree data structure. Traversal means visiting all nodes of the graph.

1. Depth-first search algorithm

    The standard DFS implementation divides each vertex of the graph into two categories:

  1. Visited
  2. Never visited

    The purpose of this algorithm is to mark each vertex as visited while avoiding loops.
    The working principle of the DFS algorithm is as follows:

  1. First put any vertex of the graph on the top of the stack.
  2. Get the top data item of the stack and add it to the visited list.
  3. Create a list of neighboring nodes of this vertex. Add those not in the access list to the top of the stack.
  4. Repeat steps 2 and 3 until the stack is empty.
2. Depth first search legend

    Let's take an example to see how the depth-first search algorithm works. We use an undirected graph with 5 vertices.
Insert picture description here
    We start from vertex 0, the DFS algorithm first puts it in the access list, and then puts all adjacent vertices on the stack.
Insert picture description here
    Next, we visit the element at the top of the stack, which is 1, and go to its neighboring node. Because 0 has already been visited, we change to visit 2.
Insert picture description here
    Vertex 2 has an unvisited adjacent vertex 4, so we add it to the top of the stack and visit it.
Insert picture description here
Insert picture description here
    After we visit the last element 3, it does not have any unvisited adjacent nodes, so we have completed the depth-first traversal of the graph.
Insert picture description here

3. DFS pseudo code (recursive implementation)

    The pseudo code of DFS is shown below. In the init() function, notice that we run the DFS function on each node. This is because the graph may have two different disconnected parts, so in order to ensure that each vertex is covered, we can run the DFS algorithm on each node.

DFS(G, u)
    u.visited = true
    for each v ∈ G.Adj[u]
        if v.visited == false
            DFS(G,v)
     
init() {
    
    
    For each u ∈ G
        u.visited = false
     For each u ∈ G
       DFS(G, u)
}
4. C example

    The code and example of the depth-first search algorithm are shown below. The code has been simplified so that we can focus on the algorithm instead of other details.

// DFS algorithm in C

#include <stdio.h>
#include <stdlib.h>

struct node {
    
    
  int vertex;
  struct node* next;
};

struct node* createNode(int v);

struct Graph {
    
    
  int numVertices;
  int* visited;

  // We need int** to store a two dimensional array.
  // Similary, we need struct node** to store an array of Linked lists
  struct node** adjLists;
};

// DFS algo
void DFS(struct Graph* graph, int vertex) {
    
    
  struct node* adjList = graph->adjLists[vertex];
  struct node* temp = adjList;

  graph->visited[vertex] = 1;
  printf("Visited %d \n", vertex);

  while (temp != NULL) {
    
    
    int connectedVertex = temp->vertex;

    if (graph->visited[connectedVertex] == 0) {
    
    
      DFS(graph, connectedVertex);
    }
    temp = temp->next;
  }
}

// Create a node
struct node* createNode(int v) {
    
    
  struct node* newNode = malloc(sizeof(struct node));
  newNode->vertex = v;
  newNode->next = NULL;
  return newNode;
}

// Create graph
struct Graph* createGraph(int vertices) {
    
    
  struct Graph* graph = malloc(sizeof(struct Graph));
  graph->numVertices = vertices;

  graph->adjLists = malloc(vertices * sizeof(struct node*));

  graph->visited = malloc(vertices * sizeof(int));

  int i;
  for (i = 0; i < vertices; i++) {
    
    
    graph->adjLists[i] = NULL;
    graph->visited[i] = 0;
  }
  return graph;
}

// Add edge
void addEdge(struct Graph* graph, int src, int dest) {
    
    
  // Add edge from src to dest
  struct node* newNode = createNode(dest);
  newNode->next = graph->adjLists[src];
  graph->adjLists[src] = newNode;

  // Add edge from dest to src
  newNode = createNode(src);
  newNode->next = graph->adjLists[dest];
  graph->adjLists[dest] = newNode;
}

// Print the graph
void printGraph(struct Graph* graph) {
    
    
  int v;
  for (v = 0; v < graph->numVertices; v++) {
    
    
    struct node* temp = graph->adjLists[v];
    printf("\n Adjacency list of vertex %d\n ", v);
    while (temp) {
    
    
      printf("%d -> ", temp->vertex);
      temp = temp->next;
    }
    printf("\n");
  }
}

int main() {
    
    
  struct Graph* graph = createGraph(4);
  addEdge(graph, 0, 1);
  addEdge(graph, 0, 2);
  addEdge(graph, 1, 2);
  addEdge(graph, 2, 3);

  printGraph(graph);

  DFS(graph, 2);

  return 0;
}
5. The complexity of depth-first search

    The time complexity of the DFS algorithm is represented by O(V+E), where V is the number of nodes and E is the number of edges.
    The space complexity of the algorithm is O(V).

6. Application of DFS algorithm
  1. Find the path
  2. Whether the test chart is a bipartite chart
  3. Strongly connected components for finding graphs
  4. Used to detect cycles in the graph
Reference documents

[1]Parewa Labs Pvt. Ltd.Depth First Search (DFS)[EB/OL].https://www.programiz.com/dsa/graph-dfs,2020-01-01.

Guess you like

Origin blog.csdn.net/zsx0728/article/details/114640856