Insert at End Tail Insert in DSA C - Time & Space Complexity
We want to understand how the time to add a new item at the end of a linked list changes as the list grows.
How does the number of steps grow when we insert at the tail?
Analyze the time complexity of the following code snippet.
// Insert a new node at the end of a singly linked list
void insertAtEnd(Node** head, int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
if (*head == NULL) {
*head = newNode;
return;
}
Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
This code creates a new node and adds it to the end of a singly linked list by traversing from the head.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves through each node until the last one.
- How many times: It runs once for each node in the list until the end, so n times if the list has n nodes.
As the list gets longer, the time to find the end grows linearly because we check each node one by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps to reach the end |
| 100 | About 100 steps to reach the end |
| 1000 | About 1000 steps to reach the end |
Pattern observation: The steps increase directly with the number of nodes, so doubling nodes doubles the work.
Time Complexity: O(n)
This means the time to insert at the end grows in direct proportion to the list size.
[X] Wrong: "Inserting at the end is always fast and takes constant time."
[OK] Correct: Without a pointer to the last node, we must walk through the whole list, so time grows with list length.
Understanding this helps you explain why adding at the tail can be slow without extra pointers, showing you know how data structure design affects speed.
"What if we kept a pointer to the last node (tail) in the list? How would the time complexity change?"
Practice
Solution
Step 1: Understand the operation
Inserting at the end means adding a new node after the current last node.Step 2: Identify the effect on the list
The new node becomes the new tail, extending the list by one node.Final Answer:
Adds a new node at the end (tail) of the list -> Option AQuick Check:
Insert at end = Add node at tail [OK]
- Confusing insert at end with insert at beginning
- Thinking it deletes a node
- Assuming it searches instead of inserts
Solution
Step 1: Understand node creation in C
We use malloc to allocate memory and cast it to pointer of struct Node.Step 2: Check syntax correctness
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); correctly casts malloc result to (struct Node*) and uses sizeof(struct Node).Final Answer:
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); -> Option DQuick Check:
Correct malloc and cast syntax = struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); [OK]
- Missing cast to (struct Node*)
- Using wrong type without struct keyword
- Assigning malloc to struct variable instead of pointer
Solution
Step 1: Understand tail insertion effect
Inserting 4 at the end adds it after 3, the current tail.Step 2: Visualize the new list
The list becomes 1 -> 2 -> 3 -> 4 -> NULL after insertion.Final Answer:
1 -> 2 -> 3 -> 4 -> NULL -> Option BQuick Check:
Insert 4 at tail = 1->2->3->4->NULL [OK]
- Inserting at head instead of tail
- Placing new node in middle
- Not updating tail pointer
void insertAtEnd(struct Node** head, int data) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
if (*head == NULL) {
*head = newNode;
} else {
struct Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp = newNode;
}
}Solution
Step 1: Analyze the while loop and insertion
The code moves temp to last node, but then does temp = newNode; which only changes temp pointer.Step 2: Identify correct linking
To link newNode, temp->next should be assigned newNode, not temp itself.Final Answer:
temp = newNode; does not link newNode to the list -> Option AQuick Check:
Link newNode by temp->next = newNode [OK]
- Assigning newNode to temp pointer instead of temp->next
- Forgetting to set newNode->next to NULL
- Not handling empty list case
Solution
Step 1: Create new node with data 40 and next NULL
This prepares the new node to be added at the end.Step 2: Traverse list to last node
Using while(temp->next != NULL) moves temp to last node (30).Step 3: Link last node's next to newNode
temp->next = newNode correctly attaches new node at end.Final Answer:
Traverse to last node with while(temp->next != NULL), then temp->next = newNode -> Option CQuick Check:
Traverse to tail, then temp->next = newNode [OK]
- Setting newNode->next to head (inserts at front)
- Not updating last node's next pointer
- Loop condition allowing temp to become NULL
Ready to prove it?
Pass the test and this pattern moves unknown
