Insert at End of Circular Linked List in DSA C - Time & Space Complexity
We want to understand how the time to insert a node at the end of a circular linked list changes as the list grows.
How does the number of steps needed grow when the list gets bigger?
Analyze the time complexity of the following code snippet.
struct Node {
int data;
struct Node* next;
};
void insertEnd(struct Node** head, int value) {
struct Node* newNode = malloc(sizeof(struct Node));
newNode->data = value;
if (*head == NULL) {
newNode->next = newNode;
*head = newNode;
return;
}
struct Node* temp = *head;
while (temp->next != *head) {
temp = temp->next;
}
temp->next = newNode;
newNode->next = *head;
*head = newNode;
}
This code inserts a new node at the end of a circular linked list by traversing to the last node.
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 until it reaches the last node, so roughly n times for a list of size n.
As the list grows, the number of steps to find the last node grows linearly.
| 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; doubling nodes doubles the steps.
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 quick and takes constant time."
[OK] Correct: Because we must find the last node by moving through the list, which takes longer as the list grows.
Understanding this helps you explain how linked list operations scale and shows you can analyze code beyond just writing it.
"What if we kept a pointer to the last node? How would the time complexity change?"
Practice
Solution
Step 1: Understand circular linked list structure
In a circular linked list, the last node points back to the head node, forming a circle.Step 2: Insert new node at end
The new node is linked after the current last node, and its next pointer points to the head node, maintaining the circle.Final Answer:
The new node becomes the last node and points back to the head node. -> Option BQuick Check:
New node points to head, preserving circular link [OK]
- Forgetting to link new node back to head
- Inserting node at wrong position
- Breaking the circular link
Solution
Step 1: Allocate memory for new node
In C, use malloc with sizeof(struct Node) and cast to (struct Node*).Step 2: Correct pointer declaration
Declare newNode as a pointer to struct Node to hold the allocated memory address.Final Answer:
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); -> Option AQuick Check:
Proper malloc and pointer cast in C [OK]
- Missing (struct Node*) cast
- Declaring newNode as struct Node instead of pointer
- Using C++ style new operator in C
struct Node {
int data;
struct Node* next;
};
void printList(struct Node* head) {
struct Node* temp = head;
if (head != NULL) {
do {
printf("%d -> ", temp->data);
temp = temp->next;
} while (temp != head);
}
printf("NULL\n");
}
int main() {
struct Node* head = (struct Node*)malloc(sizeof(struct Node));
struct Node* second = (struct Node*)malloc(sizeof(struct Node));
struct Node* third = (struct Node*)malloc(sizeof(struct Node));
head->data = 1; head->next = second;
second->data = 2; second->next = third;
third->data = 3; third->next = head;
// Insert new node with data 4 at end
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = 4;
newNode->next = head;
third->next = newNode;
printList(head);
return 0;
}Solution
Step 1: Understand list before insertion
Initial list is 1 -> 2 -> 3 -> back to 1 (circular).Step 2: Insert new node at end
New node with data 4 points to head; third node points to new node, extending list to 1 -> 2 -> 3 -> 4 -> back to 1.Step 3: Print list
printList prints nodes until it reaches head again, so output is 1 -> 2 -> 3 -> 4 -> NULL.Final Answer:
1 -> 2 -> 3 -> 4 -> NULL -> Option DQuick Check:
New node added at end, circular link maintained [OK]
- Printing infinite loop by not stopping at head
- Forgetting to update last node's next pointer
- Incorrect print format
void insertEnd(struct Node** head, int data) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = *head;
struct Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}Solution
Step 1: Analyze loop condition in circular list
In a circular linked list, last node's next points to head, not NULL.Step 2: Correct loop condition
Loop should continue until temp->next equals head, not NULL, to find last node.Final Answer:
The while loop condition should check for temp->next != *head instead of NULL. -> Option CQuick Check:
Loop must detect circular end by comparing to head [OK]
- Using NULL to detect end in circular list
- Setting newNode->next to NULL
- Not updating last node's next pointer
Solution
Step 1: Understand single node circular list
The single node has head->next pointing to itself (head).Step 2: Insert at end
Set newNode->next = head->next (which is head), then head->next = newNode. This makes head -> newNode -> head, maintaining circularity without changing head.Final Answer:
Create new node, set newNode->next = head->next, set head->next = newNode. -> Option AQuick Check:
head -> newNode -> head [OK]
- Setting newNode->next to NULL breaking circularity
- Unnecessarily updating head to newNode
- Incorrectly linking new node to itself
Ready to prove it?
Pass the test and this pattern moves unknown
