C Programs | IT Developer
IT Developer

C Programs



Share with a Friend

Data Structures in C

Graph Representation using Adjacency List

What is an Adjacency List?

An Adjacency List represents a graph as an array of linked lists.

  • Each vertex in the array has a linked list of vertices that are directly connected to it.
  • It’s very efficient for sparse graphs (few edges compared to vertices).

Structure Overview

If there are V vertices, you maintain an array of size V, where each element points to a linked list of neighbors.

graph[0] → 1 → 2

graph[1] → 0 → 3

graph[2] → 0 → 3

graph[3] → 1 → 2

Example Graph

Consider the same undirected graph as before:

0 — 1

|   |

2 — 3

Adjacency List Representation:

Vertex

Adjacent Vertices

0

1 → 2

1

0 → 3

2

0 → 3

3

1 → 2

 

C Program: Graph Representation using Adjacency List

C

#include <stdio.h>

#include <stdlib.h>

 

// Structure for adjacency list node

struct Node {

    int vertex;

    struct Node* next;

};

 

// Structure for the graph

struct Graph {

    int vertices;

    struct Node** adjLists; // array of pointers to linked lists

};

 

// Create a new adjacency list node

struct Node* createNode(int v) {

    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));

    newNode->vertex = v;

    newNode->next = NULL;

    return newNode;

}

 

// Create a graph with given vertices

struct Graph* createGraph(int vertices) {

    struct Graph* graph = (struct Graph*)malloc(sizeof(struct Graph));

    graph->vertices = vertices;

 

    // Create an array of adjacency lists

    graph->adjLists = (struct Node**)malloc(vertices * sizeof(struct Node*));

 

    // Initialize each adjacency list as empty

    for (int i = 0; i < vertices; i++)

        graph->adjLists[i] = NULL;

 

    return graph;

}

 

// Add an edge (undirected)

void addEdge(struct Graph* graph, int src, int dest) {

    // Add edge from src to dest

    struct Node* newNode = createNode(dest);

    newNode->next = graph->adjLists[src];

    graph->adjLists[src] = newNode;

 

    // Add edge from dest to src (because undirected)

    newNode = createNode(src);

    newNode->next = graph->adjLists[dest];

    graph->adjLists[dest] = newNode;

}

 

// Print adjacency list representation

void displayGraph(struct Graph* graph) {

    printf("\nAdjacency List Representation:\n");

    for (int i = 0; i < graph->vertices; i++) {

        struct Node* temp = graph->adjLists[i];

        printf("Vertex %d:", i);

        while (temp) {

            printf(" -> %d", temp->vertex);

            temp = temp->next;

        }

        printf("\n");

    }

}

 

// Main function

int main() {

    int vertices, edges;

    printf("Enter number of vertices: ");

    scanf("%d", &vertices);

 

    struct Graph* graph = createGraph(vertices);

 

    printf("Enter number of edges: ");

    scanf("%d", &edges);

 

    printf("Enter edges (u v):\n");

    for (int i = 0; i < edges; i++) {

        int u, v;

        scanf("%d %d", &u, &v);

        addEdge(graph, u, v);

    }

 

    displayGraph(graph);

 

    return 0;

}

Output

 
INPUT :
Enter number of vertices: 4
Enter number of edges: 4
Enter edges (u v):
0 1
0 2
1 3
2 3

OUTPUT :
Adjacency List Representation:
Vertex 0: -> 2 -> 1
Vertex 1: -> 3 -> 0
Vertex 2: -> 3 -> 0
Vertex 3: -> 2 -> 1

Complexity Analysis

Operation

Time Complexity

Space Complexity

Insert Edge

O(1)

O(V + E)

Check Edge

O(degree of vertex)

O(V + E)

Traverse Graph

O(V + E)

O(V + E)

Much more space-efficient than adjacency matrix for large, sparse graphs.

Key Takeaways

  • Best for sparse graphs (few edges).
  • Uses linked lists to store neighbors dynamically.
  • Efficient traversal and edge storage.
  • Checking whether an edge exists is slower than matrix (O(degree)).
  • Perfect for DFS, BFS, and Graph Algorithms like Dijkstra’s, Prim’s, etc.