Connected Components Using BFS in DSA C - Time & Space Complexity
We want to understand how long it takes to find all connected parts in a graph using BFS.
How does the time needed grow as the graph gets bigger?
Analyze the time complexity of the following code snippet.
void bfs(int start, int n, int adj[][n], int visited[]) {
int queue[n], front = 0, rear = 0;
queue[rear++] = start;
visited[start] = 1;
while (front != rear) {
int node = queue[front++];
for (int i = 0; i < n; i++) {
if (adj[node][i] && !visited[i]) {
queue[rear++] = i;
visited[i] = 1;
}
}
}
}
int countConnectedComponents(int n, int adj[][n]) {
int visited[n];
for (int i = 0; i < n; i++) visited[i] = 0;
int count = 0;
for (int i = 0; i < n; i++) {
if (!visited[i]) {
bfs(i, n, adj, visited);
count++;
}
}
return count;
}
This code finds how many connected groups are in a graph using BFS traversal.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: BFS visits each node and checks all its possible neighbors (scans matrix row).
- How many times: Each node is visited once, and for each node all n possible neighbors are checked.
As the graph grows, BFS processes all n nodes and scans n rows of the matrix (n checks each).
| Input Size (n) | Approx. Operations |
|---|---|
| 10 nodes | About 100 (n2) |
| 100 nodes | About 10,000 (n2) |
| 1000 nodes | About 1,000,000 (n2) |
Pattern observation: The work grows roughly with the square of the number of nodes.
Time Complexity: O(n2)
This means the time grows quadratically with the number of nodes (for adjacency matrix).
[X] Wrong: "BFS takes O(n) time because each node is visited once."
[OK] Correct: Node visits are O(n), but neighbor checks scan O(n) matrix entries per node, totaling O(n2).
Understanding BFS time complexity helps you explain graph traversal efficiency clearly, a key skill in many coding challenges.
"What if the graph was represented using adjacency lists instead of a matrix? How would the time complexity change?"
Practice
Solution
Step 1: Understand BFS traversal in undirected graphs
BFS explores all nodes reachable from a given start node by visiting neighbors level by level.Step 2: Connect BFS to connected components
By running BFS from an unvisited node, we find all nodes in that node's connected component.Final Answer:
All nodes reachable from a starting node forming one connected component -> Option AQuick Check:
BFS finds connected components by exploring reachable nodes [OK]
- Thinking BFS only finds shortest paths
- Confusing connected components with edge counts
- Assuming BFS finds node degrees
visited and current node u?Solution
Step 1: Understand marking visited nodes
To mark a node visited, assign true to visited[u], indicating it is visited.Step 2: Check syntax correctness
Using visited[u] = true; correctly assigns the boolean true. Using == is a comparison, not assignment.Final Answer:
visited[u] = true; -> Option BQuick Check:
Assign true to mark visited[u] [OK]
- Using == instead of = for assignment
- Assigning 0 instead of true to visited
- Assigning null which is invalid in C
int n = 5;
int adj[5][5] = {
{0,1,0,0,0},
{1,0,0,0,0},
{0,0,0,1,1},
{0,0,1,0,0},
{0,0,1,0,0}
};
bool visited[5] = {false};
int count = 0;
for (int i = 0; i < n; i++) {
if (!visited[i]) {
bfs(i, adj, visited, n);
count++;
}
}
printf("%d\n", count);
Solution
Step 1: Analyze adjacency matrix for connected components
Nodes 0 and 1 are connected; nodes 2, 3, 4 form another connected group.Step 2: Count connected components using BFS
BFS from node 0 visits nodes 0 and 1; BFS from node 2 visits nodes 2, 3, 4. Total components = 2.Final Answer:
2 -> Option AQuick Check:
Two groups found by BFS = 2 [OK]
- Counting edges instead of components
- Misreading adjacency matrix connections
- Forgetting to mark visited nodes
void bfs(int start, int adj[][5], bool visited[], int n) {
queue<int> q;
q.push(start);
visited[start] = true;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v = 0; v < n; v++) {
if (adj[u][v] == 1 && visited[v] == false) {
q.push(v);
}
}
}
}Solution
Step 1: Check BFS neighbor processing
When a neighbor v is found unvisited, it must be marked visited immediately to avoid re-adding.Step 2: Identify missing visited mark
The code pushes v to queue but does not mark visited[v] = true; causing repeated visits.Final Answer:
Missing visited[v] = true; inside the loop -> Option DQuick Check:
Mark visited when enqueueing neighbors [OK]
- Marking visited only after popping from queue
- Incorrect queue initialization
- Wrong loop condition for BFS
Solution
Step 1: Identify connected components from edges
Edges connect nodes into groups: {0,1,2}, {3,4}, {5,6}. Since nodes are numbered 0 to 6, there are no other nodes.Step 2: Count connected components
Groups are: {0,1,2}, {3,4}, {5,6} -> 3 components total.Step 3: BFS calls equal connected components
Each BFS call finds one component, so minimum BFS calls = 3.Final Answer:
3 -> Option CQuick Check:
Number of BFS calls = number of connected components [OK]
- Counting edges instead of components
- Miscounting isolated nodes
- Assuming BFS calls equal nodes
Ready to prove it?
Pass the test and this pattern moves unknown
