Sound Waves in Matlab
Sound Waves in Matlab
Experiment Title:
Implementation of Graph
Batch: BSEE Teacher:
2021-25 Dr. Kamran Safdar
Semester 8th Lab Engineer:
M Hunzilah Ahmad
Adam Abbas
12.1 Abstract
This lab focuses on the implementation of graph data structures in Python, par-
ticularly using adjacency matrix and adjacency list representations. It aims to
deepen understanding of graph-based modeling through the development of ba-
sic operations such as adding and removing edges, and simulating directed and
undirected graphs. Additionally, the experiment provides insight into how these
data structures support efficient graph traversal and management, which are es-
sential in solving real-world computational problems.
12.2 Objectives
The primary objectives of this lab are:
12.3 Background
A graph is a fundamental non-linear data structure used to model relationships
between entities. It consists of a set of vertices (nodes) and edges (links) connect-
ing pairs of vertices. Graphs can be directed or undirected, and are widely used
in networking, routing, and social media analysis. In this lab, two core rep-
resentations—adjacency matrix and adjacency list—are explored to understand
their advantages and use cases.
Task 1
1
Lab 12
1 class UndirectedGraph:
2 def __init__(self, vertices):
3 self.V = vertices
4 self.adj_matrix = [[0] * vertices for _ in range(
vertices)]
5 self.adj_list = {i: [] for i in range(vertices)}
6
7 def add_edge(self, u, v):
8 # Adjacency Matrix
9 self.adj_matrix[u][v] = 1
10 self.adj_matrix[v][u] = 1
11 # Adjacency List
12 self.adj_list[u].append(v)
13 self.adj_list[v].append(u)
14
15 def remove_edge(self, u, v):
16 # Adjacency Matrix
17 self.adj_matrix[u][v] = 0
18 self.adj_matrix[v][u] = 0
19 # Adjacency List
20 if v in self.adj_list[u]: self.adj_list[u].remove(v)
21 if u in self.adj_list[v]: self.adj_list[v].remove(u)
22
23 def display(self):
24 print("Adjacency Matrix:")
25 for row in self.adj_matrix:
26 print(row)
27 print("\nAdjacency List:")
28 for key in self.adj_list:
29 print(f"{key}: {self.adj_list[key]}")
30
31
32 # Initialize graph
33 ug = UndirectedGraph(5)
34 edges = [(0, 1), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (3,
4)]
35
36 for u, v in edges:
37 ug.add_edge(u, v)
38
39 ug.display()
40
41 # Example: remove edge (1, 4)
42 ug.remove_edge(1, 4)
43 print("\nAfter removing edge (1, 4):")
44 ug.display()
2
Lab 12
Result
The graph with 5 vertices and 7 edges was successfully represented using both adja-
cency matrix and adjacency list. After removing the edge between vertex 1 and
vertex 4, both representations were correctly updated (see Figure 12.1).
Figure 12.1: Representation of an Undirected Graph before and after Edge Removal
Task 2
1 class DirectedGraph:
2 def __init__(self, vertices):
3 self.V = vertices
4 self.adj_matrix = [[0] * vertices for _ in range(
vertices)]
5 self.adj_list = {i: [] for i in range(vertices)}
6
7 def add_edge(self, u, v):
8 # Adjacency Matrix
9 self.adj_matrix[u][v] = 1
10 # Adjacency List
11 self.adj_list[u].append(v)
12
13 def display(self):
14 print("Adjacency Matrix:")
3
Lab 12
Result
A directed graph with 4 vertices and 5 edges was created and represented using
adjacency matrix and adjacency list. The output accurately reflects one-way
connections from source to destination vertices (see Figure 12.2).
Figure 12.2: Representation of a Directed Graph Using Adjacency Matrix and Adja-
cency List
– Time Complexity:
∗ Add/Remove Edge: O(1)
∗ Check Edge Existence: O(1)
∗ Traverse All Neighbors: O(V )
– Space Complexity: O(V 2 )
4
Lab 12
• Adjacency List:
– Time Complexity:
∗ Add Edge: O(1) (amortized)
∗ Remove Edge / Check Existence: O(k), where k is the number of
neighbors
∗ Traverse All Neighbors: O(k)
– Space Complexity: O(V + E)
The adjacency matrix is suitable for dense graphs where quick edge access is
required, while the adjacency list is more efficient for sparse graphs due to its lower
space usage.
12.4 Discussion
• The lab reinforced the understanding of graph representations using both ad-
jacency matrices and adjacency lists.
12.5 Conclusion
In this lab, we successfully implemented graph data structures using both adja-
cency matrix and adjacency list representations. By performing edge operations
and analyzing time-space trade-offs, we gained insights into selecting the appropri-
ate structure for different applications. The experiment enhanced our understanding
of graph traversal, storage optimization, and the functional distinction between
directed and undirected graphs. Overall, this lab served as a practical foundation
for applying graph theory in real-world computing problems.