CSE 331 Spring 2008, Section 1
Homework 8 Solutions
1.
For reference source code, see the Homework-1/hw08/ folder on the course web site.
2.
The time complexities given here ignore the time spent building the graph.
In case you're
curious, the reference implementation on the course web site takes O(E log N) time to get the
graph set up.
For each of the E edges, the starting and destination cities are looked up in a map
of city names.
This takes O(log N) time per lookup.
The rest of the graph-building loop is made
up of miscellaneous O(1) tasks.
Interestingly, O(E log N) is worse than the running times for depth-first and breadth-first search.
It is also worse than the running time for Dijkstra's algorithm on a dense graph.
Depth-first search:
Time complexity:
There are N cities in the graph.
If the city popped off the stack has already
been visited, it will be skipped and the next city on the stack will be processed instead.
Thus, we
will only explore each city once.
Since we explore each city once, we will process each
adjacency list exactly once.
This is an undirected graph, so each edge will appear in two separate
adjacency lists.
We will therefore process a total of 2E adjacency list entries, where E is the
number of edges in the graph.
Because of how the adjacency lists are stored, it only takes O(1) effort to look up a city's
adjacency list.
Furthermore, it only takes O(1) effort for each adjacency list entry to read the
entry and push the corresponding vertex onto the stack.
Since we do O(1) effort for each of the
N vertices and O(1) effort for each of the 2E adjacency list entries, the total runtime for the
depth-first search will be O(N + E).
After the search completes, a path needs to be traced from the destination city to the starting city.
In the worst case, the search will have to visit every single vertex in the graph before it reaches
the destination.
O(1) work is done for each vertex in the path, so the worst-case running time of
this path-tracing will be O(N).
Since N = O(N + E), the overall running time of O(N + E) still
stands.
Space complexity:
First, we consider the space occupied by the graph.
As noted above, there are
2E adjacency list entries.
These are all stored in vectors, requiring a total of O(E) space.
The
adjacency lists themselves are indexed by another vector, requiring O(N) space.
A map is also
used for associating city names with their index in the adjacency lists.
Assuming a binary search
tree implementation, this map will also require O(N) space, since there will be a node in the tree
for each city.
The total space complexity of the graph structure is therefore O(N + E).
Now we consider any extra memory consumed while the algorithm is running.
We maintain
vectors to track whether each vertex has been visited or not and also to remember the road
leading back toward the starting point from each vertex.
These two vectors will have one
constant-size entry for each vertex, so they will only require O(N) space.
Next, we have a stack for keeping track of which vertex we should visit next.