Theory

The same algorithm, a different answer

In lesson 5 you showed that recursion and an explicit stack are the same algorithm, and you measured it:

recursive                        80             40
iterative (your stack)           80             40
identical — same algorithm, different place to keep the stack

Here you have both versions on a graph. And they disagree.

  path from 0 to 705
  DFS (stack)                 214
  DFS (recursive)               1

  the two DFS versions agree: false

The test says how often:

the two DFS versions took different paths to 552 destinations

Out of 554 reachable — 552.

Was lesson 5 wrong

No. It is still right; it just needs saying precisely what about.

What was the same is still the same. Both versions visit the same nodes, do the same amount of work, cost O(V + E), and agree on what is reachable — TestBothSearchesAgreeOnReachability requires exactly that, and it passes.

What differs is the order of the neighbours. The stack version pushes them all and takes the last, so it walks them backwards. The recursive version goes in order from the first. The same square, opposite directions.

"The same algorithm" means "computes the same thing", not "returns the same answer". When there are many correct answers, the order decides which one you get.

DFS returns a path. Neither of these two is more correct than the other.

Where the equivalence actually ends

Lesson 5 found a second difference too — depth. Here it is on a graph, in a chain-shaped library:

n= 4000000  iterative DFS: ok=true  hops=3999999
n= 4000000  recursive DFS: ok=true  hops=3999999

n=12000000  iterative DFS: ok=true  hops=11999999
n=12000000  recursive DFS:
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

Four million — both work. Twelve million — the iterative one walks the whole chain and the recursive one dies.

The cause is the one lesson 5 measured: the call stack grows to a 1 GB limit and stops there. Your stack is a slice on the heap, and it has no such limit.

And now it is no longer a demonstration:

  • recursion is shorter — DFS fits in six lines instead of ten;
  • iteration has no depth limit and lets you control the visiting order;
  • BFS has no recursive form at all — layers need a queue, and the call stack is a stack.

Lesson 4 said transit writes its BFS iteratively with an explicit queue. Now it is clear that it could not do otherwise: recursion gives you a stack, and BFS needs a queue. There is no choice there. The choice is DFS's alone.