Adjacency List Representation in DSA C - Time & Space Complexity
We want to understand how the time to build and use an adjacency list changes as the graph grows.
How does the number of nodes and edges affect the work done?
Analyze the time complexity of the following code snippet.
// Create adjacency list for graph with n vertices and edges array
void createAdjList(int n, int edges[][2], int edgesCount, List adjList[]) {
for (int i = 0; i < n; i++) {
adjList[i] = createEmptyList();
}
for (int i = 0; i < edgesCount; i++) {
int u = edges[i][0];
int v = edges[i][1];
addToList(adjList[u], v);
addToList(adjList[v], u); // for undirected graph
}
}
This code builds an adjacency list for an undirected graph by adding each edge to the lists of both connected nodes.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Loop over all edges to add connections.
- How many times: The loop runs once for each edge, twice adding nodes to lists.
As the number of edges grows, the work grows roughly twice as fast because each edge adds two entries.
| Input Size (edgesCount) | Approx. Operations |
|---|---|
| 10 | About 20 additions to lists |
| 100 | About 200 additions to lists |
| 1000 | About 2000 additions to lists |
Pattern observation: The operations grow linearly with the number of edges.
Time Complexity: O(n + e)
This means the time grows linearly with the number of nodes plus the number of edges.
[X] Wrong: "The time depends only on the number of nodes (n)."
[OK] Correct: The edges (connections) also matter because each edge adds work to the lists.
Understanding adjacency list complexity helps you explain graph storage and traversal efficiency clearly in interviews.
"What if the graph was directed and we only added one direction per edge? How would the time complexity change?"
Practice
Solution
Step 1: Understand adjacency list concept
An adjacency list stores each vertex and the vertices it connects to directly.Step 2: Compare with other representations
Unlike adjacency matrix, adjacency list focuses on neighbors per vertex, not a full matrix.Final Answer:
A list where each vertex stores its adjacent vertices -> Option AQuick Check:
Adjacency list = vertex with neighbors [OK]
- Confusing adjacency list with adjacency matrix
- Thinking it stores only edges without vertices
- Assuming it lists vertices without connections
Solution
Step 1: Understand adjacency list declaration
Adjacency list uses array of pointers to linked list nodes, so 'struct Node* adjList[5];' is correct.Step 2: Check other options
int adjList[5][5]; is adjacency matrix, C is array of structs (not pointers), A is array of int pointers (not nodes).Final Answer:
struct Node* adjList[5]; -> Option DQuick Check:
Array of pointers to nodes = correct adjacency list declaration [OK]
- Using 2D array instead of array of pointers
- Declaring array of structs instead of pointers
- Using int pointers instead of node pointers
struct Node {
int vertex;
struct Node* next;
};
struct Node* adjList[3] = {NULL, NULL, NULL};
// Adding edge 0->1
struct Node* newNode = malloc(sizeof(struct Node));
newNode->vertex = 1;
newNode->next = adjList[0];
adjList[0] = newNode;
// Adding edge 0->2
newNode = malloc(sizeof(struct Node));
newNode->vertex = 2;
newNode->next = adjList[0];
adjList[0] = newNode;
// Adding edge 1->2
newNode = malloc(sizeof(struct Node));
newNode->vertex = 2;
newNode->next = adjList[1];
adjList[1] = newNode;
// Print adjacency list for vertex 0
struct Node* temp = adjList[0];
while(temp != NULL) {
printf("%d -> ", temp->vertex);
temp = temp->next;
}
printf("NULL\n");What is the printed output?
Solution
Step 1: Trace insertion order for vertex 0
Edges 0->1 then 0->2 are added at head, so list is 2 -> 1 -> NULL.Step 2: Understand print loop
Prints vertices in order from head: 2 then 1, then NULL.Final Answer:
2 -> 1 -> NULL -> Option CQuick Check:
Last inserted edge appears first in adjacency list [OK]
- Assuming order is insertion order instead of reversed
- Printing vertex 0 itself in adjacency list
- Confusing NULL print format
void addEdge(struct Node* adjList[], int u, int v) {
struct Node* newNode = malloc(sizeof(struct Node));
newNode->vertex = v;
newNode->next = NULL;
adjList[u] = newNode;
}What is the main problem with this code?
Solution
Step 1: Analyze pointer assignment
Setting adjList[u] = newNode overwrites old list head, losing previous edges.Step 2: Check linked list linking
newNode->next is NULL, so no link to old list; old edges lost.Final Answer:
It overwrites existing adjacency list for vertex u, losing previous edges -> Option AQuick Check:
Overwriting head pointer loses old adjacency list [OK]
- Not linking new node to existing list
- Forgetting to allocate memory
- Incorrectly setting next pointer
- 0 -> 1
- 0 -> 2
- 1 -> 2
- 2 -> 0
- 2 -> 3
- 3 -> 3
Which data structure and insertion method correctly represents this graph in C?
Solution
Step 1: Choose correct data structure
Adjacency list uses array of pointers to linked nodes for each vertex.Step 2: Insert edges properly
Insert new nodes at head, linking to previous list to keep all edges.Step 3: Check other options
Use 2D int array; set 1 for edges and 0 otherwise is adjacency matrix, C overwrites lists losing edges, D lacks linking.Final Answer:
Use array of pointers to Node structs; insert new nodes at head linking to old list -> Option BQuick Check:
Array of pointers + head insertion = correct adjacency list [OK]
- Using adjacency matrix instead of list
- Overwriting adjacency list on insertion
- Not linking nodes properly
Ready to prove it?
Pass the test and this pattern moves unknown
