Proofs: Nonrecursive depth-first search
These are the human proofs of Nonrecursive depth-first search, at full length.
Nonrecursive DFS produces the same times and parents as recursive DFS full
This proof shows: correctness, termination.
Fix a graph , an order of and an order of each list. Let be the recursive procedure DFS of the depth-first search page and the procedure ITERATIVE-DFS. We show that they compute the same , and .
Steps. Cut the run of into steps. A root step is one test of line L4 of (with the call it may start, up to the discovery of its root). Inside a call DFS-VISIT, an edge step is one test of a list entry by the loop, with the discovery of if is white, and an end step is the end of the call, which sets . Cut the run of in the same way: a root step is one test of line L4, an edge step is one execution of lines L9 to L11, and an end step is one execution of line L12.
Claim. Consider the two runs after they have done the same number of steps of the same kinds since the same root step. Then:
- both have the same colours, times and , parents and clock;
- the stack of lists, from bottom to top, exactly the vertices whose calls in are active, from the oldest to the newest;
- for each on , the call of in has tested exactly the first entries of .
Proof. By induction on the number of steps. At the start, nothing has happened in either run, both clocks are 0, is empty and no call is active.
Root step. Both runs are in their outer loops with no active call and an empty stack, by part 2, and they test the same vertex , which has the same colour in both, by part 1. If is white, calls DFS-VISIT, which makes gray and sets to the next clock value, and does the same at line L5 and pushes , with and no entry tested. All three parts hold.
Step inside a tree. Let be the newest active call of , which is the call that runs. By part 2, is the top of , so line L7 gets the same . By part 3, 's loop in the call of has tested entries.
- If , the loop of tests the entry next, and line L9 reads the same and increases . If is white (the same in both runs), sets and calls DFS-VISIT, which makes gray and sets , and does the same at line L11 and pushes on top of . The new call is the newest, with no entry tested, and because was white and is pushed for the first time. If is not white, neither run changes anything else.
- If , the call of in has tested its whole list, so it makes black, sets and returns, and the next active call is the one below it. Line L12 does the same and pops .
In each case, the two runs make the same change, and all three parts hold again.
Termination. Each edge step increases some , which never exceeds and is never reset, because a vertex is pushed only while it is white and is then gray or black for ever. Each end step pops a vertex, and each vertex is pushed at most once. So the loop of line L6 runs at most times in total, where is the total length of the lists, and terminates.
Theorem. ITERATIVE-DFS returns the same , and as the recursive DFS with the same orders.
Proof. The runs of and have the same sequence of steps by the claim: whenever one of them can do an edge step or an end step, so can the other, and when the stack is empty, both are in the outer loop at the same vertex. When terminates, all of its steps are matched by steps of , both outer loops have tested all vertices, and part 1 gives the same , and .