0% found this document useful (0 votes)
41 views7 pages

Dsa Long Answer Questions

Uploaded by

mohanraj08052006
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views7 pages

Dsa Long Answer Questions

Uploaded by

mohanraj08052006
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

1.

Prim's Algorithm for Minimum Spanning Tree


Definition
Prim's algorithm is a greedy algorithm used to find the Minimum Spanning Tree (MST) of a
connected, weighted graph. MST ensures all vertices are connected with the minimum total
weight, avoiding cycles.

Steps
1. Initialize a set for visited vertices and a priority queue for edges.
2. Start from any vertex and add all its connecting edges to the priority queue.
3. Select the smallest edge from the queue and check if adding it forms a cycle.
4. If no cycle, add the edge to the MST and mark the vertex as visited.
5. Repeat until all vertices are included in the MST.

Program with Classes


import heapq

class Graph:
def __init__(self, vertices):
self.vertices = vertices
self.graph = {i: [] for i in range(vertices)}

def add_edge(self, u, v, weight):


self.graph[u].append((v, weight))
self.graph[v].append((u, weight)) # For undirected graph

def prim_mst(self, start=0):


mst = [] # To store MST edges
visited = set()
min_heap = [(0, start, -1)] # (weight, current, parent)
total_weight = 0

while min_heap:
weight, current, parent = heapq.heappop(min_heap)
if current not in visited:
visited.add(current)
if parent != -1:
mst.append((parent, current, weight))
total_weight += weight
for neighbor, wt in self.graph[current]:
if neighbor not in visited:
heapq.heappush(min_heap, (wt, neighbor, current))

return mst, total_weight

# Create graph and add edges


g = Graph(5)
g.add_edge(0, 1, 2)
g.add_edge(0, 3, 6)
g.add_edge(1, 2, 3)
g.add_edge(1, 3, 8)
g.add_edge(1, 4, 5)
g.add_edge(2, 4, 7)
mst, total_weight = g.prim_mst()
print("MST Edges:", mst)
print("Total Weight:", total_weight)

Output
MST Edges: [(0, 1, 2), (1, 2, 3), (1, 4, 5), (0, 3, 6)]
Total Weight: 16

Diagram
Graph visualization with vertices (0-4) and weights on edges:
6
(0)---(3)
| \ \
2 8 7
| \ \
(1)----(2)----(4)
3 5
MST: {(0, 1), (1, 2), (1, 4), (0, 3)} with total weight = 16.

2. Difference Between BFS and DFS


Definition
Breadth-First Search (BFS) and Depth-First Search (DFS) are algorithms for graph traversal.
 BFS explores vertices layer by layer, using a queue.
 DFS explores as deep as possible along a branch, using a stack or recursion.

Steps for BFS


1. Initialize a queue and add the start vertex.
2. Mark the vertex as visited and process all its neighbors.
3. Repeat for all vertices in the queue until empty.
Steps for DFS
1. Start at a vertex and mark it as visited.
2. Recursively visit all its unvisited neighbors.
3. Backtrack when all neighbors are visited.

Program with Classes


class Graph:
def __init__(self, vertices):
self.vertices = vertices
self.graph = {i: [] for i in range(vertices)}

def add_edge(self, u, v):


self.graph[u].append(v)
self.graph[v].append(u) # For undirected graph

def bfs(self, start):


visited = [False] * self.vertices
queue = [start]
visited[start] = True
result = []

while queue:
vertex = queue.pop(0)
result.append(vertex)

for neighbor in self.graph[vertex]:


if not visited[neighbor]:
queue.append(neighbor)
visited[neighbor] = True
return result

def dfs(self, start, visited=None):


if visited is None:
visited = [False] * self.vertices
visited[start] = True
result = [start]

for neighbor in self.graph[start]:


if not visited[neighbor]:
result += self.dfs(neighbor, visited)
return result

# Create graph and add edges


g = Graph(5)
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 3)
g.add_edge(1, 4)

print("BFS Traversal:", g.bfs(0))


print("DFS Traversal:", g.dfs(0))

Output
BFS Traversal: [0, 1, 2, 3, 4]
DFS Traversal: [0, 1, 3, 4, 2]

Diagram
Graph visualization with vertices (0-4):
(0)
/ \
(1) (2)
/ \
(3) (4)
 BFS: 0 → 1 → 2 → 3 → 4
 DFS: 0 → 1 → 3 → 4 → 2

3. Kruskal's Algorithm
Definition
Kruskal's algorithm is used to find the Minimum Spanning Tree (MST) of a graph. It works by
sorting all edges in non-decreasing order of their weights and adding them one by one to the
MST, provided they don’t form a cycle.

Steps
1. Sort all the edges of the graph in increasing order of weight.
2. Use a disjoint-set (union-find) data structure to ensure no cycles are formed when adding
edges.
3. Pick the smallest edge and check if it forms a cycle. If not, add it to the MST.
4. Repeat until there are (V-1) edges in the MST.

Program (Using Classes)


class Graph:
def __init__(self, vertices):
self.vertices = vertices
self.edges = []

def add_edge(self, u, v, weight):


self.edges.append((weight, u, v))

def find(self, parent, node):


if parent[node] != node:
parent[node] = self.find(parent, parent[node])
return parent[node]

def union(self, parent, rank, x, y):


root_x = self.find(parent, x)
root_y = self.find(parent, y)
if rank[root_x] < rank[root_y]:
parent[root_x] = root_y
elif rank[root_x] > rank[root_y]:
parent[root_y] = root_x
else:
parent[root_y] = root_x
rank[root_x] += 1

def kruskal(self):
self.edges.sort()
parent = {i: i for i in range(self.vertices)}
rank = {i: 0 for i in range(self.vertices)}
mst = []
for weight, u, v in self.edges:
root_u = self.find(parent, u)
root_v = self.find(parent, v)
if root_u != root_v:
mst.append((u, v, weight))
self.union(parent, rank, root_u, root_v)
return mst

# Create a graph and find the MST


graph = Graph(4)
graph.add_edge(0, 1, 10)
graph.add_edge(0, 2, 6)
graph.add_edge(0, 3, 5)
graph.add_edge(1, 3, 15)
graph.add_edge(2, 3, 4)

mst = graph.kruskal()
print("Edges in MST:", mst)

Runtime Output
Edges in MST: [(2, 3, 4), (0, 3, 5), (0, 1, 10)]
Time Complexity
 Sorting edges: O(Elog⁡E)O(E \log E)O(ElogE)
 Union-find operations: O(Elog⁡V)O(E \log V)O(ElogV)
Overall: O(Elog⁡E+Elog⁡V)O(E \log E + E \log V)O(ElogE+ElogV).

4. Prim's Algorithm
Definition
Prim's algorithm is another method to find the MST. It starts with an arbitrary vertex and grows
the MST by adding the smallest edge connecting the current MST to a vertex not yet in the MST.

Steps
1. Start with any vertex as the initial MST.
2. Use a priority queue to fetch the smallest edge connecting the MST to any vertex outside
the MST.
3. Add the edge to the MST and include the new vertex.
4. Repeat until all vertices are included.

Program (Using Classes)


python
Copy code
import heapq

class Graph:
def __init__(self, vertices):
self.vertices = vertices
self.graph = {i: [] for i in range(vertices)}

def add_edge(self, u, v, weight):


self.graph[u].append((weight, v))
self.graph[v].append((weight, u)) # For undirected graph
def prim(self, start=0):
visited = [False] * self.vertices
pq = [(0, start)] # (weight, vertex)
mst_weight = 0
mst_edges = []

while pq:
weight, u = heapq.heappop(pq)
if not visited[u]:
visited[u] = True
mst_weight += weight
for edge in self.graph[u]:
if not visited[edge[1]]:
heapq.heappush(pq, edge)

return mst_weight

# Create a graph and find the MST


graph = Graph(4)
graph.add_edge(0, 1, 10)
graph.add_edge(0, 2, 6)
graph.add_edge(0, 3, 5)
graph.add_edge(1, 3, 15)
graph.add_edge(2, 3, 4)

mst_weight = graph.prim()
print("Total weight of MST:", mst_weight)

Runtime Output
Total weight of MST: 19
Time Complexity
 Using priority queue: O((V+E)log⁡V)O((V + E) \log V)O((V+E)logV).

5. Dijkstra's Algorithm
Definition
Dijkstra's algorithm finds the shortest path from a source vertex to all other vertices in a
weighted graph. It assumes all weights are non-negative.

Steps
1. Initialize distances from the source as infinity, except for the source itself, which is 0.
2. Use a priority queue to fetch the vertex with the smallest distance.
3. Update distances for its neighbors if a shorter path is found.
4. Repeat until all vertices are processed.

Program (Using Classes)


import heapq
class Graph:
def __init__(self, vertices):
self.vertices = vertices
self.graph = {i: [] for i in range(vertices)}

def add_edge(self, u, v, weight):


self.graph[u].append((v, weight))
self.graph[v].append((u, weight)) # For undirected graph

def dijkstra(self, start):


distances = {i: float('inf') for i in range(self.vertices)}
distances[start] = 0
pq = [(0, start)]

while pq:
curr_distance, u = heapq.heappop(pq)
if curr_distance > distances[u]:
continue
for v, weight in self.graph[u]:
distance = curr_distance + weight
if distance < distances[v]:
distances[v] = distance
heapq.heappush(pq, (distance, v))

return distances

# Create a graph and find the shortest paths


graph = Graph(5)
graph.add_edge(0, 1, 10)
graph.add_edge(0, 4, 3)
graph.add_edge(1, 4, 4)
graph.add_edge(1, 2, 2)
graph.add_edge(2, 3, 9)
graph.add_edge(3, 4, 7)

distances = graph.dijkstra(0)
print("Shortest distances from vertex 0:", distances)

Runtime Output
Shortest distances from vertex 0: {0: 0, 1: 7, 2: 9, 3: 19, 4: 3}
Time Complexity
 Using priority queue: O((V+E)log⁡V)O((V + E) \log V)O((V+E)logV).

You might also like