La recherche en profondeur (DFS) est l’autre algorithme fondamental de parcours de graphe; La première, la recherche en largeur (BFS), est son antonyme. Aussi utile que le BFS, le DFS peut être utilisé pour générer un ordre topologique, générer des labyrinthes (cf. générateurs de labyrinthe DFS), pour traverser les arbres dans un ordre spécifique, pour construire des arbres de décisions, pour découvrir un chemin de solution avec des choix hiérarchiques, pour détecter un cycle dans un graphe...

Cependant, veuillez d'abord noter que le DFS ne garantit pas le chemin le plus court.
De ce fait, ce n’est pas un très bon algorithme si le seul but est de une recherche simple de chemin entre deux noeuds.

La recherche en profondeur taverse en explorant chaque chemin le plus loin possible avant de devoir revenir en arrière. C’est la raison pour laquelle vous pouvez également trouver cet algorithme sous le nom de Backtracking (Retour en arrière). De plus, cette propriété permet de mettre en oeuvre l'algorithme succinctement à la fois sous forme itérative et récursive. Si nous considérons une arborescence (qui est un graphe simplifié), la DFS procédera comme suit:


Étapes

  • Ajouter le noeud de départ dans la pile et marquez comme visité.
  • Tant qu'il y a un noeud dans la pile:
  • 1. Prendre le noeud au dessus de la pile.
  • 2. Ajouter sur la pile tous les voisins disponibles dans l'ordre, noter le parent et marquer comme visité.
    (nous avons choisi pour la visualisation Nord, Est, Sud, Ouest comme ordre)
  • Fini : obtenir le chemin en utilisant le parent depuis la fin.
DFS utilise la stratégie opposée à celle de la recherche en largeur qui explore cercle par cercle. Pourtant, les deux algorithmes ont les mêmes lignes de code; la seule différence réside dans la structure de données utilisée:

Stack (Pile) data structure - LIFO - DFS Queue data structure - FIFO - BFS
DFS utilise une Stack - Pile (LIFO) BFS utilise une Queue (FIFO)

Code

DFS(Maze maze, Node start, Node end)
{
  // Put the start node in the stack
  start.visite = true;
  Stack stack(start);

  // While there is node to be handled in the stack
  while (!stack.empty())
  {
    // Handle the node on the top of the stack and retrieve its unvisited neighbors
    Node curNode = stack.pop();

    // Terminate if the goal is reached
    if (curNode == end)
      break;

    // Take unvisited neighbors in order (eg. Noth, East, South, West),
    // set its parent, mark as visited, and add to the stack
    auto neighbors = curNode.GetUnvisitedNeighbors();
    for (auto i = 0; i < neighbors.size(); ++i)
    {
      neighbors[i].visite = true;
      neighbors[i].parent = curNode;
      stack.push(neighbors[i]);
    }
  }

  // Done ! At this point we just have to walk back from the end using the parent
  // If end does not have a parent, it means that it has not been found.
} 

Version Récursive

La récursivité de l’algorithme DFS provient du fait que nous ajoutons les contextes sur la call stack tant que nous n’avons pas atteint une impasse. Lorsque nous revenons en arrière, nous supprimons le context en haut de la pile d’appels. Plus que des mots, le code parle de lui-même ^^

bool Recursive_DFS(Maze maze, Node start, Node end)
{
  // Terminate if the goal is reached
  if (start == end)
    return true;

  // Visite current node
  start.visite = true;

  // Take unvisited neighbors in order (eg. North, East, South, West),
  auto neighbors = start.GetUnvisitedNeighbors();
  for (auto i = 0; i < neighbors.size(); ++i)
  {
    neighbors[i].parent = start;

    // Recurse and Terminate if the goal is reached
    if (Recursive_DFS(maze, neighbors[i], end)) return true;
  }

  return false;
}