C Graphs – Learn Graph Data Structure in C
A graph is a non-linear data structure made up of nodes (also called vertices) and edges connecting them. In this tutorial, we will explore how to represent graphs in C and implement various graph algorithms.
๐น What is a Graph?
A graph consists of a finite set of vertices (or nodes) and a set of edges (or arcs) that connect pairs of vertices. There are two main types of graphs:
- Directed Graph: Edges have a direction, i.e., they point from one vertex to another.
- Undirected Graph: Edges have no direction, i.e., they simply connect two vertices.
๐ Example 1: Graph Representation in C (Adjacency Matrix)
In this example, we represent a graph using an adjacency matrix. The matrix is a 2D array where each element represents an edge between two vertices.
#include <stdio.h>
#define MAX_VERTICES 5
// Function to display the adjacency matrix of the graph
void displayGraph(int graph[MAX_VERTICES][MAX_VERTICES]) {
printf("Graph (Adjacency Matrix):\n");
for (int i = 0; i < MAX_VERTICES; i++) {
for (int j = 0; j < MAX_VERTICES; j++) {
printf("%d ", graph[i][j]);
}
printf("\n");
}
}
int main() {
// Adjacency matrix for an undirected graph
int graph[MAX_VERTICES][MAX_VERTICES] = {
{0, 1, 0, 1, 0},
{1, 0, 1, 0, 1},
{0, 1, 0, 0, 1},
{1, 0, 0, 0, 0},
{0, 1, 1, 0, 0}
};
// Display the graph
displayGraph(graph);
return 0;
}
๐น Graph Traversals (BFS and DFS)
Graph traversal refers to the process of visiting all the vertices in a graph. There are two primary traversal methods:
- Depth-First Search (DFS): Explores as far down a branch as possible before backtracking.
- Breadth-First Search (BFS): Explores all the neighbors of a vertex before moving on to the next level.
๐ Example 2: Depth-First Search (DFS)
DFS is implemented using recursion or a stack. It starts at the root (or any arbitrary node), explores as far as possible along each branch, and then backtracks.
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTICES 5
// Function to perform DFS traversal
void dfs(int graph[MAX_VERTICES][MAX_VERTICES], int visited[MAX_VERTICES], int vertex) {
printf("%d ", vertex);
visited[vertex] = 1;
// Recur for all adjacent vertices
for (int i = 0; i < MAX_VERTICES; i++) {
if (graph[vertex][i] == 1 && !visited[i]) {
dfs(graph, visited, i);
}
}
}
int main() {
// Adjacency matrix for an undirected graph
int graph[MAX_VERTICES][MAX_VERTICES] = {
{0, 1, 0, 1, 0},
{1, 0, 1, 0, 1},
{0, 1, 0, 0, 1},
{1, 0, 0, 0, 0},
{0, 1, 1, 0, 0}
};
int visited[MAX_VERTICES] = {0};
// Perform DFS starting from vertex 0
printf("DFS Traversal: ");
dfs(graph, visited, 0);
printf("\n");
return 0;
}
๐ Example 3: Breadth-First Search (BFS)
BFS uses a queue data structure to explore vertices level by level. It is implemented iteratively.
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTICES 5
// Queue structure for BFS
struct Queue {
int items[MAX_VERTICES];
int front;
int rear;
};
void initQueue(struct Queue* q) {
q->front = -1;
q->rear = -1;
}
int isEmpty(struct Queue* q) {
return q->front == -1;
}
void enqueue(struct Queue* q, int value) {
if (q->rear == MAX_VERTICES - 1) {
printf("Queue Full\n");
} else {
if (q->front == -1) {
q->front = 0;
}
q->rear++;
q->items[q->rear] = value;
}
}
int dequeue(struct Queue* q) {
if (isEmpty(q)) {
printf("Queue Empty\n");
return -1;
} else {
int item = q->items[q->front];
q->front++;
if (q->front > q->rear) {
q->front = q->rear = -1;
}
return item;
}
}
// Function to perform BFS traversal
void bfs(int graph[MAX_VERTICES][MAX_VERTICES], int visited[MAX_VERTICES], int start) {
struct Queue q;
initQueue(&q);
visited[start] = 1;
enqueue(&q, start);
while (!isEmpty(&q)) {
int vertex = dequeue(&q);
printf("%d ", vertex);
// Visit all the adjacent vertices
for (int i = 0; i < MAX_VERTICES; i++) {
if (graph[vertex][i] == 1 && !visited[i]) {
visited[i] = 1;
enqueue(&q, i);
}
}
}
}
int main() {
// Adjacency matrix for an undirected graph
int graph[MAX_VERTICES][MAX_VERTICES] = {
{0, 1, 0, 1, 0},
{1, 0, 1, 0, 1},
{0, 1, 0, 0, 1},
{1, 0, 0, 0, 0},
{0, 1, 1, 0, 0}
};
int visited[MAX_VERTICES] = {0};
// Perform BFS starting from vertex 0
printf("BFS Traversal: ");
bfs(graph, visited, 0);
printf("\n");
return 0;
}
๐ฏ Key Takeaways
- A graph consists of vertices and edges, and can be represented using an adjacency matrix or an adjacency list.
- Graph traversal can be done using DFS (Depth-First Search) or BFS (Breadth-First Search).
- Both traversal methods are useful for exploring and searching graphs.
๐ Practice Time!
Try modifying the graph representation or traversal methods. Experiment with directed graphs and create your own graph algorithms like detecting cycles or finding the shortest path!