Non-récursive Depth-First Search (DFS) à l'Aide d'une Pile

Ok c'est mon premier post sur un Débordement de Pile, j'ai lu un peu de temps et vraiment admirer le site. J'espère que c'est quelque chose qui sera acceptable pour les poser. Donc, j'ai entrepris la lecture de l'Intro à l'Algorithmique (Cormen. MIT Press) tout le chemin à travers et je suis prêt à les algorithmes sur les graphes. J'ai étudié la procédure formelle d'algorithmes prévues pour la largeur et la profondeur de recherche dans des détails très fins.

Voici le pseudo-code pour depth-first search:

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

Cet algorithme est récursif et il produit à partir de sources multiples (découverts tous les sommets disjoints graphique). Il a plusieurs propriétés que la plupart des implémentations spécifiques pourraient quitter. Il distingue entre 3 différentes couleurs des sommets. Au départ, il peint tout en blanc, puis quand ils sont "découverts" (consulté le DFS-VISITE), ils sont ensuite peints en gris. Le DFS-VISITE de l'algorithme exécute une boucle récursive de l'appel lui-même sur la liste d'adjacence de l'actuel sommet et seulement les peintures d'un sommet noir quand il n'a plus de bords pour toute blanche nœud.

Également deux autres attributs de chaque sommet sont maintenus à l'u.d et u.f est le moment de timbres lorsque le sommet a été découvert (peint en gris) ou lorsque l'un des sommets est fini (peint en noir). La première fois qu'un nœud est peint, il a un timbre de temps de l'un, et il est incrémenté de la valeur entière suivante pour chaque fois qu'un autre est peint (qu'il soit gris ou noir). u.π est également entretenu qui est un pointeur vers le nœud à partir duquel u a été découvert.

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

* MODIFIER 10/31/12 * C'est embarrassant que mon algorithme a été incorrect pendant si longtemps, il serait de travailler dans la plupart des cas, mais pas tous. J'ai juste une question populaire badge pour la question et j'ai vu où Irfy avait repéré le problème dans sa réponse ci-dessous, c'est donc là que le crédit va. Je suis juste de le fixer ici pour quelqu'un qui a besoin de cela dans l'avenir.

Personne ne voir une faille avec l'algorithme ci-dessus? Je suis de loin pas un expert en théorie des graphes, mais je pense que j'ai une assez bonne emprise sur la récursivité et itération et je crois que cela devrait fonctionner de la même. Je suis à la recherche pour le rendre fonctionnellement équivalent à l'algorithme récursif. Il doit conserver tous les attributs du premier algorithme, même si elles ne sont pas nécessaires.

Quand j'ai commencé à l'écrire, je ne pense pas que j'aurais un triplement des boucles, mais c'est la façon dont il s'est avéré. J'ai vu d'autres algorithmes itératifs quand j'ai regardé autour de Google, qui ne disposent que d'une double boucle imbriquée, cependant, ils ne semblent pas procéder à partir de plusieurs sources. (c'est à dire qu'ils ne seront pas de découvrir à chaque vertex sans lien graphique)

Merci d'indentation après if énoncé dans la deuxième boucle dans le deuxième algorithme. Idéalement également le retrait après la première for boucle
Faites le modifier tout à l'heure, c'est ce que j'avais à l'origine.
Le temps de finition calculée par la non-récursive version sera mauvais. u.f <-temps ne peut être définie qu'après tous les descendants ont leur temps d'arrivée ensemble. Si l'on prend le même exemple en CLRS, puis le nœud u aurait un temps d'arrivée=3, alors que la valeur réelle ont été de 8.
Le calcul des temps de la fin est mauvaise, merci de corriger cela.
PLC déclare que chaque sommet est d'abord blanche jusqu'à ce qu'il est d'abord examiné (découvert) à quel point il est grisé et u.d à la nouvelle heure. Il reste gris jusqu'à la liste d'adjacence est examiné complètement (u.d est définie sur tous les nœuds adjacents), à quel point il est blackend et l'heure de fin u.f à la nouvelle heure.

OriginalL'auteur Cory Gross | 2012-04-26