C Program for BFS (Breadth First Search) with Example
enqueue and dequeue functions.Examples
How to Think About It
Algorithm
Code
#include <stdio.h> #include <stdbool.h> #define MAX 5 int queue[MAX], front = -1, rear = -1; bool visited[MAX] = {false}; int graph[MAX][MAX] = { {0,1,1,0,0}, {1,0,1,1,0}, {1,1,0,1,0}, {0,1,1,0,1}, {0,0,0,1,0} }; void enqueue(int val) { if (rear == MAX - 1) return; if (front == -1) front = 0; queue[++rear] = val; } int dequeue() { if (front == -1 || front > rear) return -1; return queue[front++]; } void bfs(int start) { enqueue(start); visited[start] = true; while (front <= rear) { int current = dequeue(); if (current == -1) break; printf("%d ", current); for (int i = 0; i < MAX; i++) { if (graph[current][i] && !visited[i]) { enqueue(i); visited[i] = true; } } } } int main() { bfs(0); return 0; }
Dry Run
Let's trace BFS starting from node 0 on the given graph.
Initialize
Queue: empty, visited: all false
Start BFS
Enqueue 0, visited[0] = true; Queue: [0]
Dequeue 0
Print 0; Check neighbors 1 and 2; enqueue 1 and 2; visited[1]=true, visited[2]=true; Queue: [1,2]
Dequeue 1
Print 1; Check neighbors 0,2,3; 0 and 2 visited; enqueue 3; visited[3]=true; Queue: [2,3]
Dequeue 2
Print 2; Check neighbors 0,1,3; all visited; Queue: [3]
Dequeue 3
Print 3; Check neighbors 1,2,4; 1 and 2 visited; enqueue 4; visited[4]=true; Queue: [4]
Dequeue 4
Print 4; Check neighbor 3 visited; Queue empty; End
| Queue | Visited nodes | Printed nodes |
|---|---|---|
| [0] | [0] | |
| [1,2] | [0,1,2] | 0 |
| [2,3] | [0,1,2,3] | 0 1 |
| [3] | [0,1,2,3] | 0 1 2 |
| [4] | [0,1,2,3,4] | 0 1 2 3 |
| [] | [0,1,2,3,4] | 0 1 2 3 4 |
Why This Works
Step 1: Use a queue to track nodes
BFS uses a queue to explore nodes in the order they are discovered, ensuring nodes closer to the start are visited first.
Step 2: Mark nodes visited when enqueued
Marking nodes as visited when adding to the queue prevents revisiting and infinite loops.
Step 3: Process nodes until queue empty
Dequeue nodes one by one, print them, and enqueue their unvisited neighbors to cover the graph layer by layer.
Alternative Approaches
#include <stdio.h> #include <stdbool.h> #define MAX 5 int graph[MAX][MAX] = { {0,1,1,0,0}, {1,0,1,1,0}, {1,1,0,1,0}, {0,1,1,0,1}, {0,0,0,1,0} }; bool visited[MAX] = {false}; void bfs_recursive(int queue[], int front, int rear) { if (front > rear) return; int current = queue[front]; printf("%d ", current); for (int i = 0; i < MAX; i++) { if (graph[current][i] && !visited[i]) { visited[i] = true; queue[++rear] = i; } } bfs_recursive(queue, front + 1, rear); } int main() { int queue[MAX]; int front = 0, rear = 0; queue[rear] = 0; visited[0] = true; bfs_recursive(queue, front, rear); return 0; }
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define MAX 5 typedef struct Node { int vertex; struct Node* next; } Node; Node* adjacencyList[MAX]; bool visited[MAX] = {false}; typedef struct Queue { int items[MAX]; int front, rear; } Queue; void enqueue(Queue* q, int value) { if (q->rear == MAX - 1) return; if (q->front == -1) q->front = 0; q->items[++q->rear] = value; } int dequeue(Queue* q) { if (q->front == -1 || q->front > q->rear) return -1; return q->items[q->front++]; } void addEdge(int src, int dest) { Node* newNode = malloc(sizeof(Node)); newNode->vertex = dest; newNode->next = adjacencyList[src]; adjacencyList[src] = newNode; } void bfs(int start) { Queue q = {.front = -1, .rear = -1}; enqueue(&q, start); visited[start] = true; while (q.front <= q.rear) { int current = dequeue(&q); if (current == -1) break; printf("%d ", current); Node* temp = adjacencyList[current]; while (temp) { if (!visited[temp->vertex]) { enqueue(&q, temp->vertex); visited[temp->vertex] = true; } temp = temp->next; } } } int main() { for (int i = 0; i < MAX; i++) adjacencyList[i] = NULL; addEdge(0,1); addEdge(0,2); addEdge(1,0); addEdge(1,2); addEdge(1,3); addEdge(2,0); addEdge(2,1); addEdge(2,3); addEdge(3,1); addEdge(3,2); addEdge(3,4); addEdge(4,3); bfs(0); return 0; }
Complexity: O(V + E) time, O(V) space
Time Complexity
BFS visits each vertex once and checks all edges once, so the time is proportional to vertices plus edges, O(V + E).
Space Complexity
The queue and visited array use space proportional to the number of vertices, O(V).
Which Approach is Fastest?
Using adjacency lists is generally faster and more memory efficient for sparse graphs compared to adjacency matrices.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Adjacency Matrix BFS | O(V^2) | O(V^2) | Dense graphs or small graphs |
| Adjacency List BFS | O(V + E) | O(V + E) | Sparse graphs and large graphs |
| Recursive BFS | O(V + E) | O(V) + call stack | Small graphs; less common |