❖ Problems on Graphs |
What kind of problems do we want to solve on graphs?
While these problems are expressed as problems on graphs, they are interesting because many real world problems can be mapped onto graphs, and the solutions to the above could then be applied in solving them.
❖ Graph Traversal |
Many of the above problems can be solved by
❖ ... Graph Traversal |
Consider two related problems on graphs ...
❖ ... Graph Traversal |
There are two strategies for graph traversal/search ...
Depth-first search (DFS)
❖ ... Graph Traversal |
Comparison of BFS/DFS search for checking hasPath(a,h)
Both approaches ignore some edges by remembering previously visited vertices.
❖ ... Graph Traversal |
A spanning tree of a graph
Consider how DFS and BFS could produce its spanning tree
❖ ... Graph Traversal |
Spanning tree resulting from DFS ...
Note: choose neighbours in ascending order
❖ ... Graph Traversal |
Spanning tree resulting from BFS ...
Note: choose neighbours in ascending order
❖ Depth-first Search |
Depth-first search can be described recursively as
visited = {} depthFirst(G,v): | visited = visited ∪ {v} | for all (v,w) ∈ edges(G) do | | if w ∉ visited then | | | depthFirst(G,w) | | end if | end for
The recursion induces backtracking
❖ ... Depth-first Search |
Recursive DFS path checking
visited = {} hasPath(G,src,dest): | Input graph G, vertices src,dest | Output true if there is a path from src to dest, | false otherwise | | return dfsPathCheck(G,src,dest)
Requires wrapper around recursive function dfsPathCheck()
❖ ... Depth-first Search |
Recursive function for path checking
dfsPathCheck(G,v,dest): | visited = visited ∪ {v} | for all (v,w) ∈ edges(G) do | | if w=dest then // found edge to dest | | return true | | else if w ∉ visited then | | if dfsPathCheck(G,w,dest) then | | return true // found path via w to dest | | end if | | end if | end for | return false // no path from v to dest
❖ Depth-first Traversal Example |
Tracing the execution of dfsPathCheck(G,0,5)
Reminder: we consider neighbours in ascending order
Clearly does not find the shortest path
❖ DFS Cost Analysis |
Cost analysis:
❖ Path Finding |
Knowing whether a path exists can be useful
Knowing what the path is, is even more useful
Strategy:
Requires a global array (not a set):
visited[v]
w
v
❖ ... Path Finding |
Function to find path src→dest and print it
visited[] // store previously visited node // for each vertex 0..nV-1 findPath(G,src,dest): | Input graph G, vertices src,dest | | for all vertices v∈G do | visited[v]=-1 | end for | visited[src]=src // starting node of the path | if dfsPathCheck(G,src,dest) then | | // show path in dest..src order | | v=dest | | while v≠src do | | print v"-" | | v=visited[v] | | end while | | print src | end if
❖ ... Path Finding |
Recursive function to build path in visited[]
dfsPathCheck(G,v,dest): | for all (v,w) ∈ edges(G) do | | if visited[w] = -1 then | | visited[w] = v | | if w = dest then // found edge from v to dest | | return true | | else if dfsPathCheck(G,w,dest) then | | return true // found path via w to dest | | end if | | end if | end for | return false // no path from v to dest
❖ ... Path Finding |
DFS can also be described non-recursively (via a stack):
visited[] // store previously visited node // for each vertex 0..nV-1 findPathDFS(G,src,dest): | Input graph G, vertices src,dest | | for all vertices v∈G do | visited[v]=-1 | end for | found=false | visited[src]=src | push src onto new stack S | while not found ∧ S is not empty do | | pop v from S | | if v=dest then | | found=true | | else | | | for each (v,w)∈edges(G) with visited[w]=-1 do | | | visited[w]=v | | | push w onto S | | | end for | | end if | end while | if found then | display path in dest..src order | end if
Uses standard stack operations ... Time complexity is still O(V+E)
❖ Breadth-first Search |
Basic approach to breadth-first search (BFS):
❖ ... Breadth-first Search |
BFS path finding algorithm:
visited[] // store previously visited node // for each vertex 0..nV-1 findPathBFS(G,src,dest): | Input graph G, vertices src,dest | | for all vertices v∈G do | visited[v]=-1 | end for | found=false | visited[src]=src | enqueue src into queue Q | while not found ∧ Q is not empty do | | dequeue v from Q | | if v=dest then | | found=true | | else | | | for each (v,w) ∈ edges(G) with visited[w]=-1 do | | | visited[w]=v | | | enqueue w into Q | | | end for | | end if | end while | if found then | display path in dest..src order | end if
Uses standard queue operations (enqueue, dequeue, check if empty)
❖ ... Breadth-first Search |
Time complexity of BFS: O(V+E) (same as DFS)
BFS finds a "shortest" path
In many applications, edges are weighted and we want path
Produced: 22 Jun 2020