You are on page 1of 49

Graph in Data Structure

Introduction to Graph in Data Structure


Graphs are non-linear data structures comprising a nite
set of nodes and edges. The nodes are the elements, and
edges are ordered pairs of connections between the nodes.

Notice the word non-linear. A non-linear data structure is


one where the elements are not arranged in sequential
order. For example, an array is a linear data structure
because it is arranged one after the other. You can traverse
all the elements of an array in a single run. Such is not the
case with non-linear data structures. The elements of a
non-linear data structure are arranged in multiple levels,
often following a hierarchical pattern. Graphs are non-linear.

The next word to pay attention to is nite. We de ne the


graph to have a nite and countable number of nodes. This
is a rather non-agreeable term. Essentially, a Graph may
have an in nite number of nodes and still be nite. For
example, a family tree ranging back to Adam and Eve. This
is a relatively in nite graph but is still countable and is thus
considered nite.

Real-World Example

The best example of graphs in the real world is Facebook.


Each person on Facebook is a node and is connected
through edges. Thus, a is a friend of B. B is a friend of C,
and so on.
fi
fi
fi
fi
fi
fi
fi
fi
Terminologies

Here are the Terminologies of Graph in Data Structure


mentioned below

1. Graph Representation: Generally, a graph is


represented as a pair of sets (V, E). V is the set of vertices or
nodes. E is the set of Edges. In the above example,
V = { A, B, C, D, E }
E = { AB, AC, AD, BE, CD, DE }

2. Node or Vertex: The elements of a graph are connected


through edges.

3. Edges: A path or a line between two vertices in a graph.

4. Adjacent Nodes: Two nodes are called adjacent if they


are connected through an edge. Node A is adjacent to
nodes B, C, and D in the above example, but not to node E.

5. Path: Path is a sequence of edges between two nodes. It


is essentially a traversal starting at one node and ending at
another. Thus, in the example above, there are multiple
paths from node A to node E.

Path(A, E) = { AB, BE }
OR
Path(A, E) = { AC, CD, DE }
OR
Path(A, E) = { AD, DE }

The path contains a lot of nodes and each of them is


reachable.

Consider the given graph,

1 2 3 5 is a path.
1 2 3 2 1 is not a path, because a node can’t appear twice in
a path.
1 3 5 is not a path, as adjacent nodes must have an edge
and there is no edge between 1 and 3.
6. Undirected Graph: An undirected graph is one where
the edges do not specify a particular direction. The edges
are bi-directional.

Example

Thus, the edge AC can be traversed from both A to C and


C to A in this example. Similar to all the edges. A path from
node B to node C would be either { BA, AC } or { BD, DC }.

7. Directed Graph: A directed graph is one where the


edges can be traversed in a speci ed direction only.

Example
fi
Thus, in the same example, now the edges are directional.
You can only traverse the edge along its direction. There is
no path from node B to node C now.

8.Weighted Graph: A weighted graph is one where the


edges are associated with a weight. This is generally the
cost to traverse the edge.

Example
Thus, in the same example, now the edges have a certain
weight associated with them. There are two possible paths
between node A to node E.
Path1 = { AB, BD, DE }, Weight1 = 3+2+5 = 10
Path2 = { AC, CD, DE }, Weight2 = 1+3+5 = 9
Clearly, one would prefer Path2 if the goal is to reach node
E from node A with minimum cost.

Degree of Graph

It is the number of edges that go inside or outside that


node.

For undirected graphs, the degree is the number of edges


attached to a node.

Example,
D(3) = 3
D(4) = 2
Representing Graphs

• Adjacency matrix
◦ n by n matrix, where n is number of vertices
◦ A(m,n) = 1 i (m,n) is an edge, or 0 otherwise
◦ For weighted graph: A(m,n) = w (weight of edge),
or positive in nity otherwise
ff
fi
• Adjacency list
◦ Each vertex has a linked list of edges
◦ Edge stores destination and label
◦ Better when adjacency matrix is sparse

Basic Operations on Graph

Here are the Basic Operations of Graph ment ion below

1. Add/Remove Vertex

This is the simplest operation in the graph. You simply add


a vertex to a graph. It need not be connected to any other
vertex through an edge. However, you must remove all
edges originating from and ending at the deleted vertex
when removing a vertex.
2. Add/Remove Edge

This operation adds or removes an edge between two


vertices. When all the edges originating from and ending at
a vertex are deleted, the vertex becomes isolated.

3. Breadth-First Search (BFS)

This is a traversal operation in the graph. BFS horizontally


traverses the graph. This means that it traverses all the
nodes at a single level before proceeding to the next level.
The BFS algorithm starts at the top of the rst node in the
graph and then traverses all the adjacent nodes to it. Once
all the adjacent nodes are traversed, the algorithm repeats
the same procedure for child nodes.

Example
fi
Traversing the above graph in BFS fashion would result
from A -> B -> C -> D -> E -> F -> G. The algorithm starts
from node A and traverses all its adjacent nodes B, C and
D. It marks all the four nodes as visited. Once all the
adjacent nodes of A are traversed, the algorithm moves to
the rst adjacent node of A and repeats the same
procedure. In this case, the node is B, and the adjacent
nodes to B are E and F. Next, the adjacent nodes to C are
traversed. Once all the nodes are visited, the operation
ends.

4. Depth First Search (DFS)

Depth First Search or DFS traverses the graph vertically. It


starts with the root node or the rst node of the graph and
traverses all the child nodes before moving to the adjacent
nodes.

Example
fi
fi
Traversing the above graph in BFS fashion would result
from A -> B -> E -> F -> C -> G -> D. The algorithm starts
from node A and traverses all its child nodes. As soon as it
encounters B, it seems that it has further child nodes. So,
the child nodes of B are traversed before proceeding to the
next child node of A.

Real-World Implementations of Graphs

• Design of electrical circuits for power transmission.


• Design of network of interconnected computers.
• Study of the molecular, chemical and cellular structure
of any substance, e.g. Human DNA.
• Design of transport routes between cities and places
within a city.
Conclusion – Graph in Data Structure

Graphs are a bene cial concept in data structures. It has


practical implementations in almost every eld. Therefore, it
is essential to understand the basics of graph theory to
understand the graph structure’s algorithms.
This article was merely an introduction to graphs. It is just a
stepping stone. It is recommended to deep dive further into
the topic of graph theory.
fi
fi
Breadth rst search
Traversal means visiting all the nodes of a graph. Breadth
First Traversal or Breadth First Search is a recursive
algorithm for searching all the vertices of a graph or tree
data structure.

BFS algorithm
A standard BFS implementation puts each vertex of the
graph into one of two categories:

1. Visited
2. Not Visited
The purpose of the algorithm is to mark each vertex as
visited while avoiding cycles.

The algorithm works as follows:

1. Start by putting any one of the graph's vertices at the


back of a queue.
2. Take the front item of the queue and add it to the
visited list.
3. Create a list of that vertex's adjacent nodes. Add the
ones which aren't in the visited list to the back of the
queue.
4. Keep repeating steps 2 and 3 until the queue is empty.
The graph might have two di erent disconnected parts so
to make sure that we cover every vertex, we can also run
the BFS algorithm on every node
fi
ff
BFS example
Let's see how the Breadth First Search algorithm works
with an example. We use an undirected graph with 5
vertices.

Undirected graph with 5 vertices


We start from vertex 0, the BFS algorithm starts by putting
it in the Visited list and putting all its adjacent vertices in the
stack.

Visit start vertex and add its adjacent vertices to queue


Next, we visit the element at the front of queue i.e. 1 and go
to its adjacent nodes. Since 0 has already been visited, we
visit 2 instead.
Visit the rst neighbour of start node 0, which is 1
Vertex 2 has an unvisited adjacent vertex in 4, so we add
that to the back of the queue and visit 3, which is at the
front of the queue.

Visit 2 which was added to queue earlier to add its neighbours

4 remains in the queue


fi
Only 4 remains in the queue since the only adjacent node of
3 i.e. 0 is already visited. We visit it.

Visit last remaining item in the queue to check if it has unvisited neighbors
Since the queue is empty, we have completed the Breadth
First Traversal of the graph.
Depth First Search (DFS)
Depth rst Search or Depth rst traversal is a recursive
algorithm for searching all the vertices of a graph or tree
data structure. Traversal means visiting all the nodes of a
graph.

Depth First Search Algorithm


A standard DFS implementation puts each vertex of the
graph into one of two categories:

1. Visited
2. Not Visited
The purpose of the algorithm is to mark each vertex as
visited while avoiding cycles.

The DFS algorithm works as follows:

1. Start by putting any one of the graph's vertices on top


of a stack.
2. Take the top item of the stack and add it to the visited
list.
3. Create a list of that vertex's adjacent nodes. Add the
ones which aren't in the visited list to the top of the
stack.
4. Keep repeating steps 2 and 3 until the stack is empty.

Depth First Search Example


fi
fi
Let's see how the Depth First Search algorithm works with
an example. We use an undirected graph with 5 vertices.

Undirected graph with 5 vertices


We start from vertex 0, the DFS algorithm starts by putting
it in the Visited list and putting all its adjacent vertices in the
stack.

Visit the element and put it in the visited list


Next, we visit the element at the top of stack i.e. 1 and go
to its adjacent nodes. Since 0 has already been visited, we
visit 2 instead.
Visit the element at the top of stack

Vertex 2 has an unvisited adjacent vertex in 4, so we add


that to the top of the stack and visit it.

Vertex 2 has an unvisited adjacent vertex in 4, so we add that to the top of


the stack and visit it.

Vertex 2 has an unvisited adjacent vertex in 4, so we add that to the top of


the stack and visit it.
After we visit the last element 3, it doesn't have any
unvisited adjacent nodes, so we have completed the Depth
First Traversal of the graph.

After we visit the last element 3, it doesn't have any unvisited adjacent
nodes, so we have completed the Depth First Traversal of the graph.
Spanning Tree and Minimum
Spanning Tree
Before we learn about spanning trees, we need to
understand two graphs: undirected graphs and connected
graphs.

An undirected graph is a graph in which the edges do not


point in any direction (ie. the edges are bidirectional).

Undirected Graph
A connected graph is a graph in which there is always a
path from a vertex to any other vertex.
Connected Graph

Spanning tree
A spanning tree is a sub-graph of an undirected connected
graph, which includes all the vertices of the graph with a
minimum possible number of edges. If a vertex is missed,
then it is not a spanning tree.

The edges may or may not have weights assigned to them.

The total number of spanning trees with n vertices that can


be created from a complete graph is equal to n(n-2).

If we have n = 4, the maximum number of possible spanning


trees is equal to 44-2 = 16. Thus, 16 spanning trees can be
formed from a complete graph with 4 vertices.
Example of a Spanning Tree
Let's understand the spanning tree with examples below:

Let the original graph be:

Normal graph

Some of the possible spanning trees that can be created


from the above graph are:
A spanning tree
A spanning tree
A spanning tree
A spanning tree
A spanning tree
A spanning tree

Minimum Spanning Tree


A minimum spanning tree is a spanning tree in which the
sum of the weight of the edges is as minimum as possible.

Example of a Spanning Tree


Let's understand the above de nition with the help of the
example below.

The initial graph is:


fi
Weighted graph
The possible spanning trees from the above graph are:
Minimum spanning tree - 1
Minimum spanning tree - 2
Minimum spanning tree - 3
Minimum spanning tree - 4
The minimum spanning tree from the above spanning trees
is:
Minimum spanning tree
The minimum spanning tree from a graph is found using the
following algorithms:

1. Prim's Algorithm
2. Kruskal's Algorithm

Spanning Tree Applications


• Computer Network Routing Protocol
• Cluster Analysis
• Civil Network Planning

Minimum Spanning tree Applications


• To nd paths in the map
• To design networks like telecommunication networks,
water supply networks, and electrical grids.

Prim's Algorithm
Prim's algorithm is a minimum spanning tree algorithm that
takes a graph as input and nds the subset of the edges of
that graph which

• form a tree that includes every vertex


• has the minimum sum of weights among all the trees
that can be formed from the graph

How Prim's algorithm works


It falls under a class of algorithms called greedy algorithms
that nd the local optimum in the hopes of nding a global
optimum.

We start from one vertex and keep adding edges with the
lowest weight until we reach our goal.

The steps for implementing Prim's algorithm are as follows:


fi
fi
fi
fi
1. Initialize the minimum spanning tree with a vertex
chosen at random.
2. Find all the edges that connect the tree to new
vertices, nd the minimum and add it to the tree
3. Keep repeating step 2 until we get a minimum
spanning tree

Example of Prim's algorithm

Start with a weighted graph

Choose a vertex
fi
Choose the shortest edge from this vertex and add it

Choose the nearest vertex not yet in the solution

Choose the nearest edge not yet in the solution, if there are multiple choices,
choose one at random
Repeat until you have a spanning tree
Your One-Stop Solution to
Learn Kruskal Algorithm
From Scratch

A spanning tree is a subset of a graph that includes all the


graph's vertices and some of the edges of the original
graph, intending to have no cycles. A spanning tree is not
necessarily unique - it is possible for there to be multiple
spanning trees for a given graph. However, a given graph
will always have at least one spanning tree. The edges in a
spanning tree are called "branch edges," while the edges
not in the spanning tree are called "cycle edges." And this
type of graph helps nd the minimum number of edges
required to connect all vertices in a graph. It is also used to
create minimally secured networks with redundant paths.
fi
Creating Minimum Spanning Tree
Using Kruskal Algorithm
You will rst look into the steps involved in Kruskal’s
Algorithm to generate a minimum spanning tree:


Step 1: Sort all edges in increasing order of their edge
weights.
• Step 2: Pick the smallest edge.
• Step 3: Check if the new edge creates a cycle or loop
in a spanning tree.
• Step 4: If it doesn’t form the cycle, then include that
edge in MST. Otherwise, discard it.
• Step 5: Repeat from step 2 until it includes |V| - 1
edges in MST.
Using the steps mentioned above, you will generate a
minimum spanning tree structure. So, now have a look at
an example to understand this process better.

The graph G(V, E) given below contains 6 vertices and 12


edges. And you will create a minimum spanning tree T(V’,
E’) for G(V, E) such that the number of vertices in T will be 6
and edges will be 5 (6-1).
fi
If you observe this graph, you’ll nd two looping edges
connecting the same node to itself again. And you know
that the tree structure can never include a loop or parallel
edge. Hence, primarily you will need to remove these edges
from the graph structure.
fi
The next step that you will proceed with is arranging all
edges in a sorted list by their edge weights.

The Edges of the


Edge Weight
Graph
Source Vertex Destination Vertex
E F 2
F D 2
B C 3
C F 3
C D 4
B F 5
B D 6
A B 7
A C 8

After this step, you will include edges in the MST such that
the included edge would not form a cycle in your tree
structure. The rst edge that you will pick is edge EF, as it
has a minimum edge weight that is 2.
fi
Add edge FD to the spanning tree.

Add edge BC and edge CF to the spanning tree as it does


not generate any loop.
Next up is edge CD. This edge generates the loop in Your
tree structure. Thus, you will discard this edge.

Following edge CD, you have edge BF. This edge also
creates the loop; hence you will discard it.
Next up is edge BD. This edge also formulates a loop, so
you will discard it as well.
Next on your sorted list is edge AB. This edge does not
generate any cycle, so you need not include it in the MST
structure. By including this node, it will include 5 edges in
the MST, so you don’t have to traverse any further in the
sorted list. The nal structure of your MST is represented in
the image below:

The summation of all the edge weights in MST T(V’, E’) is


equal to 17, which is the least possible edge weight for any
possible spanning tree structure for this particular graph.
Moving ahead, you will learn about implementing Kruskal
algorithms using the Union Find Algorithm.
fi
BFS and DFS:
class Graph:
def __init__(self,li:list[list]) -> None:
self.adjlist = li
def BFS(self): # -> BFS
q = []
visited = set()
q.append(0)
visited.add(0)
ans = [0]
while q:
ele = q.pop(0)
for i in self.adjlist[ele]:
if i not in visited:
visited.add(i)
ans.append(i)
q.append(i)
return ans
def DFS(self): # -> DFS
visited = set()
ans = []
def helper(source):
visited.add(source)
ans.append(source)
for i in self.adjlist[source]:
if i not in visited:
helper(i)
for i in range(len(self.adjlist)):
if i not in visited:
helper(i)
return ans
g = Graph([[1,3,5],[0,2],[1,3,4],[0,2,4],[2,3,5],[0,4]])
print(g.BFS())
print(g.DFS())
Shortest path from Source to all
Nodes In Unweighted Graph:
# Shotest Path From Source to All Nodes in Unweighted Graph
class Graph:
def __init__(self,li:list[list]) -> None:
self.adjlist = li
def Shortest_path(self,source):
q = []
visited = set()
dist = [-1]*len(self.adjlist)
dist[source] = 0
q.append(source)
visited.add(source)
while q:
ele = q.pop(0)
for i in self.adjlist[ele]:
if i not in visited:
visited.add(i)
dist[i] = dist[ele]+1
q.append(i)
return dist
graph = Graph([[1,3],[0,2,3,5],[1,4,5],[0,1,4],[2,3,5],[1,2,4]])
print(graph.Shortest_path(2))
Prims Algorithm Code:
class Graph:
def __init__(self,mat:list[list]) -> None:
self.adjmat = mat
def MST(self,source):
visited = set()
V = len(self.adjmat)
path = [ oat('inf')]*V
path[source] = 0
parent = [-1]*V
for i in range(V-1):
mini_vertex = self.minimum_vertex(visited,path,V)
visited.add(mini_vertex)
for j in range(V):
if self.adjmat[mini_vertex][j] != 0 and j not in visited and
self.adjmat[mini_vertex][j]<path[j]:
path[j] = self.adjmat[mini_vertex][j]
parent[j] = mini_vertex
# Printing MST
cost = 0
for i in range(1,V):
print(f"from {i} -> {parent[i]} its Cost = {self.adjmat[parent[i]]
[i]}")
cost += self.adjmat[parent[i]][i]
print(f"Total Cost = {cost}")
def minimum_vertex(self,visited,path,V):
mini_weight = oat("inf")
mini_ele = None
for i in range(V):
if i not in visited and path[i]<mini_weight:
mini_weight = path[i]
mini_ele = i
return mini_ele
g = Graph([[0,4,6,0,0,0],[4,0,6,3,4,0],[6,6,0,1,0,0],[0,3,1,0,2,3],
[0,4,0,2,0,7],[0,0,0,3,7,0]])
g.MST(0)
fl
fl

You might also like