In lecture Monday we presented the greadth-first and depth-first search algorithms. We can describe them in pseudo-code as follows:
void BFS (vertex v) {
layer[0] = {v}; i = 0;
while (layer[i] is nonempty) {
for (each vertex u in layer[i])
for (each neighbor w of u)
if (w is not yet in any layer)
add w to layer[i+1];
i++;}}
void DFS (vertex v) {
mark v as explored;
for (each neighbor u of v)
if (u is not yet explored)
DFS(v);}
The BFS finds that level 0 is {a}, level 1 is {b,d,h}, level 2 is {c,e,g}, and
level 3 is {f}. The tree looks like this:
The DFS tree has all eight vertices in a single line, as it happens in
alphabetical order, so that h occurs at level 7. We have additional dotted
lines from a to d, a to h, b to g, c to f, and e to h.
(n≥n0→f(n)≤cg(n).
a
/ | \
b d h
| \ \
c g e
\
f
with the addition of dotted lines from d to c, h to g, h to e, g to f,
and e to f. This graph is also known as the three-dimensional
hypercube
We first need to convert the definition into an induction scheme that can prove
a property P(u) for all vertices u such that u is reachable from v. I gave
such a scheme on the board in lecture:
In this instance, we can take the predicate P(x) to be "x is marked explored
after DFS(v) has run". Then the base case is true because the code of DFS(v)
marks v as explored in line 2. For the inductive case, we let u and w be
arbitrary nodes and assume that w is marked during DFS(v) and that u is
a neighbor of w (this last is the same statement as "E(w,u)"). From the code,
we see that w can be marked explored only by DFS running on w, so we
may conclude that DFS(w) was run before or during the run of DFS(v).
When DFS(w) was run, u was one of the
neighbors considered at line 3. If u was not found to be explored in line 4,
it was marked explored at line 5. Since there is no way for it to become
unmarked, it must have been marked at the end of DFS(v). Since u and w were
arbitrary, we have proved the induction step. Since we have completed the
induction, we know that P(u) is true for all u that are reachable from v, as
desired.
Prove that if t is marked during the execution of DFS(s), then t is a descendent of s in the DFS tree. (Recall the the definition of "descendent" is recursive (and was given incorrectly on the handout in discussion) -- to be a descendent of s a node is either s itself of a child of a descendent of s.)
The induction needed here is a bit more complicated -- I apologize for not
getting it straight and writing it down before the discussion. We can make
a recursive definition of the predicate M(x,y) meaning "x is marked during
DFS(y)" from the code for DFS(y):
Actually the "base case" here is just a special case of the inductive case,
because if you have no unexplored neighbors then by definition any
predicate must be true for all of your unexplored neighbors.
So let's prove this with P(x) being the statement "for all y,
if y is marked during DFS(x), then y is a descendent of x".
For the base case,
assume that x has no unexplored neighbors. Then DFS(x) will make no recursive
calls, and thus will mark x itself and nothing else. Our base case is true,
because the (corrected) definition of "descendent" says that x is a descendent
of x.
Now for the inductive case. We assume that P(y) holds for every unexplored
neighbor y of x This means that for every such y, every node marked during
DFS(y) is a descendent of y. Now we look at all the nodes marked during DFS(x).
These consist of x itself, plus any nodes marked during DFS(y) for one of these
y's. The definition of "descendent" says that x is a descendent of x, and that
any descendent of any of these y's is a descendent of x (since each such y will
be a child of x in the tree). (Technical point: By "unexplored neighbor" we
mean "neighbor that is unexplored at the time that DFS(x) looks at it".) So
all these nodes are descendents of x, and we have proved P(x). This completes
the induction.
We want to prove that for any t and s, M(t,s) implies that t is a descendent of
s. The problem is that in the inductive case of the definition, the second
term of M(x,y) changes, which forces us to use induction on the s rather
than on t. Here is an induction scheme that proves P(x) for all x such that
DFS(x) finishes:
Last modified 21 September 2006