Creating a Singly Linked List from Scratch in DSA C - Complexity Walkthrough
When we create a singly linked list from scratch, we add nodes one by one. Understanding time complexity helps us see how the work grows as we add more nodes.
We want to know: How much time does it take to build the whole list as it gets bigger?
Analyze the time complexity of the following code snippet.
struct Node {
int data;
struct Node* next;
};
struct Node* createList(int arr[], int n) {
struct Node* head = NULL;
struct Node* tail = NULL;
for (int i = 0; i < n; i++) {
struct Node* newNode = malloc(sizeof(struct Node));
newNode->data = arr[i];
newNode->next = NULL;
if (head == NULL) {
head = newNode;
tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
}
return head;
}
This code creates a singly linked list by adding each element from an array to the end of the list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop runs through each element of the input array once.
- How many times: Exactly n times, where n is the number of elements.
Each new node is created and linked once per element, so the work grows directly with the number of elements.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 node creations and links |
| 100 | About 100 node creations and links |
| 1000 | About 1000 node creations and links |
Pattern observation: The number of operations grows linearly as the input size increases.
Time Complexity: O(n)
This means the time to create the list grows in direct proportion to the number of elements we add.
[X] Wrong: "Adding each node to the end takes constant time, so the whole list creation is faster than linear."
[OK] Correct: While adding to the end is constant time here because we keep a tail pointer, if we did not keep track of the tail, each addition would require traversing the list, making it slower.
Knowing how list creation scales helps you explain your code clearly and shows you understand how data structures work under the hood. This skill is useful in many coding tasks and interviews.
"What if we did not keep a tail pointer and instead found the end of the list each time we added a node? How would the time complexity change?"
Practice
singly linked list in data structures?Solution
Step 1: Understand singly linked list structure
A singly linked list stores elements where each node points only to the next node, forming a chain.Step 2: Compare with other data structures
Unlike arrays, singly linked lists do not provide direct index access, and unlike doubly linked lists, nodes have only one pointer.Final Answer:
To store elements in a sequence where each element points to the next -> Option BQuick Check:
Singly linked list = sequence with next pointers [OK]
- Thinking singly linked list allows direct index access
- Confusing singly linked list with doubly linked list
- Assuming automatic sorting in singly linked list
Solution
Step 1: Check pointer usage in struct
The next pointer must be a pointer to struct Node, so usestruct Node* next;.Step 2: Verify typedef correctness
typedef struct Node { int data; struct Node* next; } Node; correctly uses typedef and pointer syntax for next node.Final Answer:
typedef struct Node { int data; struct Node* next; } Node; -> Option AQuick Check:
Node struct uses pointer to struct Node for next [OK]
- Omitting 'struct' keyword before Node* inside struct
- Using 'Node* next;' without typedef defined yet
- Using 'struct Node next;' instead of pointer
- Using 'prev' pointer instead of 'next' for singly linked list
typedef struct Node {
int data;
struct Node* next;
} Node;
int main() {
Node* head = malloc(sizeof(Node));
head->data = 10;
head->next = malloc(sizeof(Node));
head->next->data = 20;
head->next->next = NULL;
Node* temp = head;
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
return 0;
}Solution
Step 1: Trace node creation and data assignment
First node data is 10, second node data is 20, linked correctly.Step 2: Trace printing loop
Loop prints data of head (10), then moves to next node (20), then stops at NULL.Final Answer:
10 20 -> Option AQuick Check:
Prints nodes in order: 10 then 20 [OK]
- Confusing order of nodes printed
- Forgetting to set next of last node to NULL
- Assuming compilation error due to missing includes (not shown)
typedef struct Node {
int data;
struct Node* next;
} Node;
int main() {
Node* head;
head->data = 5;
head->next = NULL;
return 0;
}Solution
Step 1: Check pointer initialization
head is declared but not assigned memory before accessing its members.Step 2: Understand consequences
Accessing head->data without allocation causes undefined behavior or crash.Final Answer:
head is not initialized before accessing its members -> Option CQuick Check:
Pointer must be allocated before use [OK]
- Assuming pointer is auto-initialized
- Confusing next pointer direction
- Thinking data must be pointer type
Solution
Step 1: Allocate nodes and assign data in order
Nodes must be allocated and data assigned before linking.Step 2: Link nodes in correct sequence
Link node1 to node2, node2 to node3, and node3 to NULL to end list.Final Answer:
Allocate node1, set data=1, allocate node2, set data=2, link node1->next=node2, allocate node3, set data=3, link node2->next=node3, set node3->next=NULL -> Option DQuick Check:
Correct order and linking builds list 1->2->3->NULL [OK]
- Linking nodes before allocation
- Not setting last node's next to NULL
- Linking nodes in reverse order
Ready to prove it?
Pass the test and this pattern moves unknown
