23.11.2014 Views

Data Structures and Algorithms in Java[1].pdf - Fulvio Frisone

Data Structures and Algorithms in Java[1].pdf - Fulvio Frisone

Data Structures and Algorithms in Java[1].pdf - Fulvio Frisone

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

adjacency matrix). The adjacency list structure came later, with its natural appeal<br />

<strong>in</strong> comput<strong>in</strong>g due to its faster methods for most algorithms (many algorithms do<br />

not use method areAdjacent) <strong>and</strong> its space efficiency.<br />

Most of the graph algorithms we exam<strong>in</strong>e will run efficiently when act<strong>in</strong>g upon a<br />

graph stored us<strong>in</strong>g the adjacency list representation. In some cases, however, a<br />

trade-off occurs, where graphs with few edges are most efficiently processed with<br />

an adjacency list structure <strong>and</strong> graphs with many edges are most efficiently<br />

processed with an adjacency matrix structure.<br />

13.3 Graph Traversals<br />

Greek mythology tells of an elaborate labyr<strong>in</strong>th that was built to house the monstrous<br />

M<strong>in</strong>otaur, which was part bull <strong>and</strong> part man. This labyr<strong>in</strong>th was so complex that<br />

neither beast nor human could escape it. No human, that is, until the Greek hero,<br />

Theseus, with the help of the k<strong>in</strong>g's daughter, Ariadne, decided to implement a graph<br />

traversal algorithm. Theseus fastened a ball of thread to the door of the labyr<strong>in</strong>th <strong>and</strong><br />

unwound it as he traversed the twist<strong>in</strong>g passages <strong>in</strong> search of the monster. Theseus<br />

obviously knew about good algorithm design, for, after f<strong>in</strong>d<strong>in</strong>g <strong>and</strong> defeat<strong>in</strong>g the<br />

beast, Theseus easily followed the str<strong>in</strong>g back out of the labyr<strong>in</strong>th to the lov<strong>in</strong>g arms<br />

of Ariadne. Formally, a traversal is a systematic procedure for explor<strong>in</strong>g a graph by<br />

exam<strong>in</strong><strong>in</strong>g all of its vertices <strong>and</strong> edges.<br />

13.3.1 Depth-First Search<br />

The first traversal algorithm we consider <strong>in</strong> this section is depth-first search (DFS)<br />

<strong>in</strong> an undirected graph. Depth-first search is useful for test<strong>in</strong>g a number of<br />

properties of graphs, <strong>in</strong>clud<strong>in</strong>g whether there is a path from one vertex to another<br />

<strong>and</strong> whether or not a graph is connected.<br />

Depth-first search <strong>in</strong> an undirected graph G is analogous to w<strong>and</strong>er<strong>in</strong>g <strong>in</strong> a labyr<strong>in</strong>th<br />

with a str<strong>in</strong>g <strong>and</strong> a can of pa<strong>in</strong>t without gett<strong>in</strong>g lost. We beg<strong>in</strong> at a specific start<strong>in</strong>g<br />

vertex s <strong>in</strong> G, which we <strong>in</strong>itialize by fix<strong>in</strong>g one end of our str<strong>in</strong>g to s <strong>and</strong> pa<strong>in</strong>t<strong>in</strong>g s<br />

as "visited." The vertex s is now our "current" vertex—call our current vertex u. We<br />

then traverse G by consider<strong>in</strong>g an (arbitrary) edge (u,v) <strong>in</strong>cident to the current<br />

vertex u. If the edge (u,v) leads us to an already visited (that is, pa<strong>in</strong>ted) vertex v,<br />

we immediately return to vertex u. If, on the other h<strong>and</strong>, (u, v) leads to an unvisited<br />

vertex v, then we unroll our str<strong>in</strong>g, <strong>and</strong> go to v. We then pa<strong>in</strong>t v as "visited," <strong>and</strong><br />

make it the current vertex, repeat<strong>in</strong>g the computation aboce. Eventually, we will get<br />

to a "dead-end," that is, a current vertex u such that all the edges <strong>in</strong>cident on u lead<br />

to vertices already visited. Thus, tak<strong>in</strong>g any edge <strong>in</strong>cident on u will cause us to<br />

return to u. To get out of this impasse, we roll our str<strong>in</strong>g back up, backtrack<strong>in</strong>g<br />

along the edge that brought us to u, go<strong>in</strong>g back to a previously visited vertex v. We<br />

then make v our current vertex <strong>and</strong> repeat the computation above for any edges<br />

<strong>in</strong>cident upon v that we have not looked at before. If all of v's <strong>in</strong>cident edges lead to<br />

visited vertices, then we aga<strong>in</strong> roll up our str<strong>in</strong>g <strong>and</strong> backtrack to the vertex we<br />

808

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!