Graphs - Representations & Traversal
Mind Map Summary
- Topic: Graphs - Representations & Traversal
- Representations:
- Adjacency List: An array of lists, where each list stores the neighbors of a vertex.
- Adjacency Matrix: A 2D array where each element
(i, j)
is 1 if there is an edge from vertexi
to vertexj
, and 0 otherwise.
- Trade-offs:
- Adjacency List: Space-efficient for sparse graphs, but slow to check for the existence of an edge.
- Adjacency Matrix: Fast to check for the existence of an edge, but space-inefficient for sparse graphs.
- Traversal:
- Breadth-First Search (BFS): A traversal algorithm that explores the graph level by level. It is used to find the shortest path in an unweighted graph.
- Depth-First Search (DFS): A traversal algorithm that explores the graph as far as possible along each branch before backtracking. It is used for traversal and cycle detection.
Practice Exercise
Implement BFS and DFS for a given graph. Clone a graph. Find the number of connected components in an undirected graph. Detect a cycle in a directed graph.
Answer
1. BFS and DFS:
// BFS
public void BFS(int s, int V, List<int>[] adj) {
bool[] visited = new bool[V];
Queue<int> queue = new Queue<int>();
visited[s] = true;
queue.Enqueue(s);
while (queue.Count > 0) {
s = queue.Dequeue();
Console.Write(s + " ");
foreach (int i in adj[s]) {
if (!visited[i]) {
visited[i] = true;
queue.Enqueue(i);
}
}
}
}
// DFS
public void DFSUtil(int v, bool[] visited, List<int>[] adj) {
visited[v] = true;
Console.Write(v + " ");
foreach (int i in adj[v]) {
if (!visited[i]) {
DFSUtil(i, visited, adj);
}
}
}
public void DFS(int v, int V, List<int>[] adj) {
bool[] visited = new bool[V];
DFSUtil(v, visited, adj);
}
2. Clone a Graph:
public Node CloneGraph(Node node) {
if (node == null) return null;
var map = new Dictionary<Node, Node>();
var queue = new Queue<Node>();
queue.Enqueue(node);
map[node] = new Node(node.val, new List<Node>());
while (queue.Count > 0) {
var curr = queue.Dequeue();
foreach (var neighbor in curr.neighbors) {
if (!map.ContainsKey(neighbor)) {
map[neighbor] = new Node(neighbor.val, new List<Node>());
queue.Enqueue(neighbor);
}
map[curr].neighbors.Add(map[neighbor]);
}
}
return map[node];
}
3. Number of Connected Components:
public int CountComponents(int n, int[][] edges) {
int count = 0;
bool[] visited = new bool[n];
List<int>[] adj = new List<int>[n];
for (int i = 0; i < n; i++) adj[i] = new List<int>();
foreach (var edge in edges) {
adj[edge[0]].Add(edge[1]);
adj[edge[1]].Add(edge[0]);
}
for (int i = 0; i < n; i++) {
if (!visited[i]) {
count++;
DFS(i, visited, adj);
}
}
return count;
}
4. Detect a Cycle in a Directed Graph:
public bool CanFinish(int numCourses, int[][] prerequisites) {
List<int>[] adj = new List<int>[numCourses];
for (int i = 0; i < numCourses; i++) adj[i] = new List<int>();
int[] degree = new int[numCourses];
foreach (var p in prerequisites) {
adj[p[1]].Add(p[0]);
degree[p[0]]++;
}
Queue<int> queue = new Queue<int>();
for (int i = 0; i < numCourses; i++) {
if (degree[i] == 0) queue.Enqueue(i);
}
int count = 0;
while (queue.Count > 0) {
int curr = queue.Dequeue();
count++;
foreach (int next in adj[curr]) {
degree[next]--;
if (degree[next] == 0) queue.Enqueue(next);
}
}
return count == numCourses;
}