Creating a Singly Linked List from Scratch in DSA C# - Complexity Walkthrough
When we create a singly linked list from scratch, we add elements one by one. Understanding how the time needed grows as we add more elements helps us write efficient code.
We want to know: how does the time to build the list change as the list gets longer?
Analyze the time complexity of the following code snippet.
public class Node {
public int Value;
public Node Next;
public Node(int value) { Value = value; Next = null; }
}
public class SinglyLinkedList {
public Node Head;
public void Add(int value) {
Node newNode = new Node(value);
if (Head == null) {
Head = newNode;
} else {
Node current = Head;
while (current.Next != null) {
current = current.Next;
}
current.Next = newNode;
}
}
}
This code creates a singly linked list and adds new nodes at the end one by one.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop inside the Add method that moves through the list to find the last node.
- How many times: For each new node added, the loop runs once for each existing node in the list until it reaches the end.
As we add more nodes, the time to add each new node grows because we must walk through the whole list to find the end.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 1 + 2 + ... + 10 = 55 steps |
| 100 | About 1 + 2 + ... + 100 = 5,050 steps |
| 1000 | About 1 + 2 + ... + 1000 = 500,500 steps |
Pattern observation: The total steps grow roughly like the square of the number of nodes added.
Time Complexity: O(n2)
This means that adding n nodes one by one at the end takes time proportional to n squared, because each add walks through the list.
[X] Wrong: "Adding each node takes the same constant time, so total time is O(n)."
[OK] Correct: Each add must find the end by walking through the list, so the time grows with the list length, not constant.
Understanding how adding nodes affects time helps you explain trade-offs in data structure design. This skill shows you can analyze and improve code efficiency.
"What if we kept a reference to the last node to avoid walking the list each time? How would the time complexity change?"
Practice
Singly Linked List in data structures?Solution
Step 1: Understand the structure of a singly linked list
A singly linked list stores elements in nodes where each node points to the next node, forming a chain.Step 2: Compare with other data structures
Unlike trees or arrays, singly linked lists do not have hierarchical or direct index access but maintain a linear sequence through pointers.Final Answer:
To store elements in a linear order where each element points to the next -> Option AQuick Check:
Singly Linked List = linear chain of nodes [OK]
- Confusing linked lists with arrays having direct index access
- Thinking linked lists store key-value pairs
- Assuming linked lists have hierarchical structure like trees
Solution
Step 1: Identify the correct node structure for singly linked list
A node must store data and a reference to the next node, so the next pointer type should be Node.Step 2: Check each option's correctness
public class Node { public int data; public Node next; } correctly declares data as int and next as Node. Options B and C incorrectly use int for next. public class Node { public int data; public Node previous; } uses previous which is for doubly linked lists.Final Answer:
public class Node { public int data; public Node next; } -> Option DQuick Check:
Node next pointer type = Node [OK]
- Using int type for next pointer instead of Node
- Confusing singly linked list with doubly linked list (previous pointer)
- Omitting access modifiers making members inaccessible
public class Node {
public int data;
public Node next;
public Node(int d) { data = d; next = null; }
}
public class LinkedList {
public Node head;
public void Add(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
} else {
Node temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = newNode;
}
}
public void PrintList() {
Node temp = head;
while (temp != null) {
Console.Write(temp.data + " -> ");
temp = temp.next;
}
Console.WriteLine("null");
}
}
class Program {
static void Main() {
LinkedList list = new LinkedList();
list.Add(10);
list.Add(20);
list.Add(30);
list.PrintList();
}
}Solution
Step 1: Trace the Add method calls
Adding 10 sets head to node with data 10. Adding 20 appends node with data 20 at end. Adding 30 appends node with data 30 at end.Step 2: Trace the PrintList method
PrintList starts at head and prints each node's data followed by ' -> ' until null is reached, printing "10 -> 20 -> 30 -> null".Final Answer:
10 -> 20 -> 30 -> null -> Option BQuick Check:
Nodes added in order = printed in order [OK]
- Assuming Add inserts at head instead of tail
- Forgetting to print 'null' at end
- Printing nodes in reverse order
public void Add(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
} else {
Node temp = head;
while (temp != null) {
temp = temp.next;
}
temp.next = newNode;
}
}Solution
Step 1: Analyze the while loop condition
The loop currently runs while temp != null, so it stops when temp is null, meaning temp.next is not accessible.Step 2: Correct the loop to stop at last node
The loop should run while temp.next != null to stop at the last node, so we can set temp.next = newNode safely.Final Answer:
The while loop condition should be 'temp.next != null' instead of 'temp != null' -> Option AQuick Check:
Traverse until last node (temp.next != null) [OK]
- Looping until temp is null causes null reference error
- Trying to assign next on null reference
- Misplacing node creation outside method
Reverse() in your singly linked list class that reverses the list in place. Which approach correctly reverses the list?Solution
Step 1: Understand in-place reversal logic
Reversing a singly linked list in place requires changing each node's next pointer to point to the previous node, not creating new nodes or swapping data.Step 2: Evaluate options for correctness
Iterating through the list, for each node setting its next pointer to the previous node while updating previous and current pointers until the end correctly describes the standard in-place reversal. The other options involve extra memory or inefficient operations.Final Answer:
Iterate through the list, for each node set its next pointer to the previous node, updating previous and current pointers until the end. -> Option CQuick Check:
Reverse by redirecting next pointers in place [OK]
- Creating new lists instead of reversing in place
- Swapping data instead of pointers
- Resetting head to null losing the list
Ready to prove it?
Pass the test and this pattern moves unknown
