Data Structures Lab 12 Graphs BFS DFS - R
Data Structures Lab 12 Graphs BFS DFS - R
Outline
• Introduction
• Graph Terminology
• Representation of Graphs
• BFS
• DFS
• Exercise
• Prelab Questions
GRAPHS
In real world many problems are represented in terms of objects and connections between them.
Leonhard Euler used graph theory to solve the classical Konigsberg bridge problem.
Graphs are data structures used for solving these kind of problems.
A graph may not have multiple occurrences of the same edge. If we remove this
restriction we obtain a data object referred to as a Multigraph.
Terminology
Path: a sequence of adjacent vertices.
Simple Path : path with no repeated vertices
Cyclic Path: is a path where the first and the last vertices are same.
A connected graph has path between every pair of vertices. There is no unreachable vertex.
A disconnected graph is a one which is not connected, it consists of a set of connected
components
[forest – disjoint union of tree]
for directed graph with n vertices, the maximum number of edges is n(n-1)
Sparse Graph : A graph with relatively fewer edges. E < |V| log |v|
A Directed Acyclic Graph (DAG) : is a directed graph with no cycles.
Weighted graphs: integers (weights) are assigned to each edge to represent (distances
or costs).
functions:
Graph Create() = return an empty graph
Graph InsertVertex(graph, v) = return a graph with v inserted. v has no incident edge.
Graph InsertEdge(graph, v1,v2) = return a graph with new edge between v1 and v2
Graph DeleteVertex(graph, v) = return a graph in which v and all edges incident to it are
removed
Graph DeleteEdge(graph, v1, v2) = return a graph in which the edge (v1, v2) is removed
Boolean IsEmpty(graph) = if (graph==empty graph) return TRUE else return FALSE
List Adjacent(graph,v) = return a list of all vertices that are adjacent to v
Applications of Graphs:
Representing relationships between components in electronic circuits
Transportation networks: Highway network, Flight network
Computer networks: Local area network, Internet, Web
Databases: For representing ER (Entity Relationship) diagrams in databases, for
representing dependency of tables in databases
GRAPH Representation
As in other ADTs, to manipulate graphs we need to represent them in some useful form.
Basically, there are different ways of doing this:
• Adjacency Matrix
• Adjacency List
Adjacency Matrix
In this method, we use a matrix with size V × V ( V is number of vertices)
The values of matrix are boolean.
Let us assume the matrix is Adj.
The value Adj[u, v] is set to 1 if there is an edge from vertex u to vertex v and 0 otherwise.
GRAPH Representation
Adjacency Matrix
GRAPH Representation
Adjacency Matrix
GRAPH Representation
Adjacency List
GRAPH Representation
Adjacency List
GRAPH Representation
Adjacency List
Comparing Adjacency matrix and List
From the adjacency matrix, to determine the connection of vertices is easy
Deleting a node is easier in adjacency matrix than from a list.
DFS algorithm
n number of vertices
//Initialize visited[] to false(0)
for(i=0; i<n; i++)
visited[i]=0;
void DFS(vertex i)
{
visited[i] = 1;
for each w adjacent to I
if(!visited[w])
DFS(w);
}
DFS Example 1
depth first search starting at V0: v0, v1, v3, v7, v4, v5, v2, v6
DFS Example 2
illustration for an Undirected Graph :
DFS Example 2
DFS Example 2
DFS Example 3
DFS Example 3
DFS Example 3
Applications of DFS
• The time complexity of DFS is O(V + E), if we use adjacency lists for representing the
graphs.
• This is because we are starting at a vertex and processing the adjacent nodes only if
they are not visited.
• Similarly, if an adjacency matrix is used for a graph representation, then all edges
adjacent to a vertex can’t be found efficiently, and this gives O(V2) complexity.
Topological sorting
Finding connected components
Finding articulation points (cut vertices) of the graph
Finding strongly connected components
Solving puzzles such as mazes
Breadth First Search
BFS algorithm works similar to level-order traversal of Trees.
BFS also uses a Queue, like Level order traversal
BFS starts at vertex V and marks it as visited
It then visits each of the vertices on V’s adjacency list. When all the vertices on V’s adjacency list have
been visited, it visits all the unvisited vertices that are adjacent to the first vertex on V’s adjacency list.
To implement this scheme, as we visit each vertex we place the vertex in a queue. When we have
exhausted an adjacency list, we remove a vertex from the queue and proceed by examining each of the
vertices on its adjacency list.
Unvisited vertices are visited and then placed on the queue, visited vertices are ignored.
The search is complete when the queue is empty
ALGORITHM:
void BFS(int v) {
node_ptr w;
front=rear=NULL; // initialize queue
printf(“%4d”,v); visited[v]=TRUE; addq(v);
while(front) {
v = deleteq( );
for(w=graph[v]; w; w=w->link)
{ if(!visited[w->vertex])
{
printf(“%4d”, w->vertex);
addq(w->vertex);
visited[w->vertex] = TRUE;
}
}
}
}
BFS ALGORITHM
Algorithm BFS( G, S)
initialize queue Q
visited(S)=TRUE; Enqueue (Q,S);
while(!Q.empty) do
v=Dequeue(Q); print(v);
for all vertices w adjacent to v do
if(visisted(w)==FALSE) then
{
Enqueue(Q,w);
visited(w)=TRUE;
}
end for
end while
BFS Example 1
Breadth first search starting at V0: v0, v1, v2, v3, v4, v5, v6, v7
BFS Example 2
illustration for an Undirected Graph :
BFS Example 2
BFS Example 2
BFS Example 3
BFS Example 3
Applications of BFS
• Time complexity of BFS is O(V + E), if we use adjacency lists for representing the graphs,
and O(V2) for adjacency matrix representation.
Comparing BFS and DFS, the big advantage of DFS is that it has much lower memory
requirements than BFS because it’s not required to store all of the child pointers at each
level.
Depending on the data and what we are looking for, either DFS or BFS can be
advantageous.
For example, in a family tree if we are looking for someone from younger generation and
if we assume that person would be at the bottom of the tree, then DFS is a better choice.
BFS would take a very long time to reach that last level. The DFS algorithm finds the goal
faster.
Now, if we were looking for a family member who belongs to a generation from very long
time ago, then that person would be closer to the top of the tree. In this case, BFS finds
faster than DFS.
So, the advantages of either vary depending on the data and what we are looking for.
DFS is related to preorder traversal of a tree. Like preorder traversal, DFS visits each node
before its children.
The BFS algorithm works similar to level – order traversal of the trees.
BFS visits each level one at a time, and if we know the solution we are searching for is at
a low depth, then BFS is good. DFS is a better choice if the solution is at maximum depth.
The below table in the next slide the differences between DFS and BFS in terms of their
applications.
Comparing BFS and DFS
Minimum Cost Spanning Tree
The spanning tree of a graph is subgraph that contains all the vertices and is also a tree [no cycles]
A graph may have many spanning trees.
The cost of a spanning tree of a weighted undirected graph is the sum of the costs(weights) of the
edges in the spanning tree.
A minimum cost spanning tree is a spanning tree of least cost
A spanning tree is a minimal subgraph G’ of G such that V(G’) is same as V(G) and G’ is connected
– A minimal subgraph is one with the fewest number of edges
The solution must satisfy the following constraints:
We must use only edges within the graph
We must use exactly n-1 edges (where n is number of vertices)
We may not use edges that would produce a cycle.
Kruskal’s Algorithm
Edge by edge
O(e log e)
At each stage Kruskal’s forms a forest
ALGORITHM:
T={};
while ((T has less than n-1 edges) &&(E not empty)) do
{
choose an edge (v,w) from E of lowest cost;
delete (v,w) from E;
if((v,w) does not create a cycle in T)
add(v,w) to T;
else
discard(v,w);
}
if(T contains fewer than n – 1 edges)
printf(“No spanning tree\n”);
Kruskal’s Example
Kruskal’s Example
Prim’s Algorithm
Begins from a vertex
O(n2)
At each stage Prim’s forms a Tree
ALGORITHM:
T={};
TV = {1}; /* start with vertex 1 and no edges */
While (T contains fewer than n-1 edges)
{
let(u,v) be a least cost edge such that u ∈ TV and v ∉ TV;
if (there is no such edge)
break;
add v to TV;
add (u,v) to T;
}
if (T contains fewer than n-1 edges)
printf(“No spanning tree\n”);
Prim’s Example
Prim’s Example 2
Applications of Graphs