DFS itératifs vs DFS récursifs et ordre des différents éléments
j'ai écrit un algorithme récursif DFS pour traverser un graphe:
void Graph<E, N>::DFS(Node n)
{
std::cout << ReadNode(n) << " ";
MarkVisited(n);
NodeList adjnodes = Adjacent(n);
NodeList::position pos = adjnodes.FirstPosition();
while(!adjnodes.End(pos))
{
Node adj = adjnodes.ReadList(pos);
if(!IsMarked(adj))
DFS(adj);
pos = adjnodes.NextPosition(pos);
}
}
alors j'ai écrit un algorithme DFS itératif en utilisant une pile:
template <typename E, typename N>
void Graph<E, N>::IterativeDFS(Node n)
{
Stack<Node> stack;
stack.Push(n);
while(!stack.IsEmpty())
{
Node u = stack.Read();
stack.Pop();
if(!IsMarked(u))
{
std::cout << ReadNode(u) << " ";
MarkVisited(u);
NodeList adjnodes = Adjacent(u);
NodeList::position pos = adjnodes.FirstPosition();
while(!adjnodes.End(pos))
{
stack.Push(adjnodes.ReadList(pos));
pos = adjnodes.NextPosition(pos);
}
}
}
Mon problème est que, dans un graphe dans lequel, par exemple, j'entre dans les trois nœuds 'a', 'b', 'c' avec des arcs ('a', 'b') et ('a', 'c') mon résultat est:
'a', 'b', 'c' avec le récursive DFS version, et:
'a', 'c', 'b' avec la DFS 1 itératif.
Comment obtenir la même commande? Suis-je en train de faire quelque chose de mal?
Merci!
2 réponses
les deux sont des algorithmes DFS valides . A DFS ne spécifie pas quel noeud vous voyez en premier. Il n'est pas important parce que l'ordre entre les bords n'est pas défini [rappelez-vous: les bords sont un ensemble d'habitude]. La différence est due à la façon dont vous traitez chaque nœud enfants.
dans l'approche itérative : vous insérez d'abord tous les éléments dans la pile - et puis gérer la tête de la pile [qui est le dernier noeud inséré] - ainsi le premier noeud que vous manipulez est le dernier enfant .
Dans le récursive "approche de 151920920" : Vous manipulez chaque nœud quand vous le voyez. Ainsi le premier noeud que vous manipulez est le premier enfant .
pour que le DFS itératif donne le même résultat que le DFS récursif - vous devez ajouter des éléments à la pile dans l'ordre inverse [pour chaque noeud, insérez son dernier enfant en premier et son premier enfant dernier]
ci-dessous est le code de l'échantillon (selon la réponse de @amit ci-dessus) dans C# pour la matrice de contiguïté.
using System;
using System.Collections.Generic;
namespace GraphAdjMatrixDemo
{
public class Program
{
public static void Main(string[] args)
{
// 0 1 2 3 4 5 6
int[,] matrix = { {0, 1, 1, 0, 0, 0, 0},
{1, 0, 0, 1, 1, 1, 0},
{1, 0, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0 ,0},
{0, 0, 1, 1, 1, 0, 0} };
bool[] visitMatrix = new bool[matrix.GetLength(0)];
Program ghDemo = new Program();
for (int lpRCnt = 0; lpRCnt < matrix.GetLength(0); lpRCnt++)
{
for (int lpCCnt = 0; lpCCnt < matrix.GetLength(1); lpCCnt++)
{
Console.Write(string.Format(" {0} ", matrix[lpRCnt, lpCCnt]));
}
Console.WriteLine();
}
Console.Write("\nDFS Recursive : ");
ghDemo.DftRecursive(matrix, visitMatrix, 0);
Console.Write("\nDFS Iterative : ");
ghDemo.DftIterative(matrix, 0);
Console.Read();
}
//====================================================================================================================================
public void DftRecursive(int[,] srcMatrix, bool[] visitMatrix, int vertex)
{
visitMatrix[vertex] = true;
Console.Write(vertex + " ");
for (int neighbour = 0; neighbour < srcMatrix.GetLength(0); neighbour++)
{
if (visitMatrix[neighbour] == false && srcMatrix[vertex, neighbour] == 1)
{
DftRecursive(srcMatrix, visitMatrix, neighbour);
}
}
}
public void DftIterative(int[,] srcMatrix, int srcVertex)
{
bool[] visited = new bool[srcMatrix.GetLength(0)];
Stack<int> vertexStack = new Stack<int>();
vertexStack.Push(srcVertex);
while (vertexStack.Count > 0)
{
int vertex = vertexStack.Pop();
if (visited[vertex])
continue;
Console.Write(vertex + " ");
visited[vertex] = true;
for (int neighbour = srcMatrix.GetLength(0) - 1; neighbour >= 0; neighbour--)
//for (int neighbour = 0; neighbour < srcMatrix.GetLength(0); neighbour++)
{
if (srcMatrix[vertex, neighbour] == 1 && visited[neighbour] == false)
{
vertexStack.Push(neighbour);
}
}
}
}
}
}