The wikipedia article mentions two ways to perform a DFS: using recursion and using a stack.
For completeness, I copy both here:
Using recursion
procedure DFS(G,v):
label v as discovered
for all edges from v to w in G.adjacentEdges(v) do
if vertex w is not labeled as discovered then
recursively call DFS(G,w)
Using a stack
procedure DFS-iterative(G,v):
let S be a stack
S.push(v)
while S is not empty
v ← S.pop()
if v is not labeled as discovered:
label v as discovered
for all edges from v to w in G.adjacentEdges(v) do
S.push(w)
The important thing to know here is how method calls work. There is an underlying stack, lets call is T
. Before the method gets called, it's arguments are pushed on the stack. The method then takes the arguments from that stack again, performs its operation, and pushes its result back on the stack. This result is then taken from the stack by the calling method.
As an example, consider the following snippet:
function caller() {
callResult = callee(argument1, argument2);
}
In terms of the stack T
, this is what happens (schematically):
// inside method caller
T.push(argument1);
T.push(argument2);
"call method callee"
// inside method callee
argument2 = T.pop();
argument1 = T.pop();
"do something"
T.push(result);
"return from method callee"
// inside method caller
callResult = T.pop();
This is pretty much what is happening in the second implementation: the stack is used explicitly. You can compare making the call to DFS
in the first snippet with pushing a vertex on the stack, and compare executing the call to DFS
in the first snippet with popping the vertex from the stack.
The first thing after popping vertex v
from the stack is marking it as discovered. This is equivalent to marking it as discovered as a first step in the execution of DFS
.