Insert at End Tail Insert in DSA C++ - Time & Space Complexity
We want to understand how long it takes to add a new item at the end of a linked list.
How does the time needed change as the list grows bigger?
Analyze the time complexity of the following code snippet.
struct Node {
int data;
Node* next;
};
void insertAtEnd(Node*& head, int value) {
Node* newNode = new Node{value, nullptr};
if (head == nullptr) {
head = newNode;
return;
}
Node* temp = head;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = newNode;
}
This code adds a new node with the given value at the end of a singly linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves through the list to find the last node.
- How many times: It runs once for each node in the list until the end is reached.
As the list gets longer, the time to find the end grows in a straight line with the number of nodes.
| 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 the list size doubles the work.
Time Complexity: O(n)
This means the time to insert at the end grows linearly with 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, which takes longer as the list grows.
Understanding this helps you explain how linked lists work and why keeping track of the tail can speed up insertions.
"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
Insert at End means adding a new node after the last node in the list.Step 2: Compare with other operations
Adding at the beginning is different; deleting nodes removes them, not adds.Final Answer:
Adds a new node at the end of the list -> Option AQuick Check:
Insert at End = Add node at list's tail [OK]
- Confusing tail insert with head insert
- Thinking it deletes nodes
- Assuming it inserts in the middle
Solution
Step 1: Create a new node using pointer and dynamic allocation
In C++, new nodes are created with 'new' keyword returning a pointer: Node* newNode = new Node(data);Step 2: Link the new node to the current tail and update tail pointer
Set tail->next = newNode; then update tail = newNode;Final Answer:
Node* newNode = new Node(data); tail->next = newNode; tail = newNode; -> Option AQuick Check:
Use pointer and new keyword for node creation [OK]
- Not using pointers for new nodes
- Missing 'new' keyword causing errors
- Assigning object instead of pointer
struct Node {
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};
Node* head = new Node(1);
Node* tail = head;
// Insert 2 at end
Node* newNode = new Node(2);
tail->next = newNode;
tail = newNode;
// Insert 3 at end
newNode = new Node(3);
tail->next = newNode;
tail = newNode;
// Print list
Node* temp = head;
while(temp != nullptr) {
std::cout << temp->data << " -> ";
temp = temp->next;
}
std::cout << "null";Solution
Step 1: Trace node insertions
Start with head = 1. Insert 2 at end: list is 1 -> 2. Insert 3 at end: list is 1 -> 2 -> 3.Step 2: Trace print loop
Prints nodes in order: 1, 2, 3, then prints 'null'.Final Answer:
1 -> 2 -> 3 -> null -> Option DQuick Check:
Tail insert appends nodes in order [OK]
- Confusing order of nodes
- Not updating tail pointer
- Printing reversed list
Node* newNode = new Node(5); tail = newNode; tail->next = nullptr;
Solution
Step 1: Check linking of new node
New node is created but previous tail's next is not updated to point to newNode.Step 2: Understand tail update
Updating tail pointer before linking breaks the chain; list loses connection to new node.Final Answer:
The new node is not linked to the previous tail's next pointer -> Option BQuick Check:
Always link previous tail's next before updating tail [OK]
- Updating tail before linking new node
- Forgetting to set previous tail's next
- Misordering pointer assignments
Solution
Step 1: Analyze insertion without tail pointer
Without tail pointer, inserting at end requires traversing entire list each time, which is inefficient.Step 2: Consider maintaining a tail pointer
Adding a tail pointer updated on each insertion allows direct access to last node, making insertion O(1).Final Answer:
Create a tail pointer and update it during every insertion to avoid traversal -> Option CQuick Check:
Tail pointer avoids full traversal for tail insert [OK]
- Ignoring tail pointer for efficiency
- Trying to swap data instead of pointers
- Reversing list unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
