Singly Linked List Summary
1. Array vs Linked List
- When you insert/delete in the middle of an array,
you usually have to shift all the elements after that position by one,
which takesO(N)time. - In contrast, a linked list only needs to break and reconnect links (pointers),
so the insertion/deletion itself can be done inO(1). - However, to find the element you want, you must follow the nodes one by one from the front,
so lookup/traversal takesO(N)time.
So in practice:
- If there are many searches → use an array
- If there are many insertions/deletions → use a linked list
2. Definition of a Node
The basic unit of a linked list is a node.
Roughly speaking, you can think of a node as “a box that stores information and points to the next box.”
A single node usually has two kinds of information:
data: the actual value (integer, string, struct, etc.)next: a reference (pointer) to the next node- For the last node, there is no next node, so we set
next = null.
- For the last node, there is no next node, so we set
We can draw it like this:
[ Data ] -> [ Next ]
3. Singly Linked List Structure & Creation
3.1 Creating a Single Node
Let’s create a node with the value 3:
set node1 = node(3) # data = 3, next = null
Or, create an empty node and then set its data:
set node1 = node() # empty node
node1.data = 3
# next has default value null
At this point, node1 is just a standalone node and does not yet belong to any list.
3.2 Connecting Two Nodes
Now create a new node node2 with value 5 and attach it after node1:
set node2 = node(5) # data = 5, next = null
node1.next = node2 # connect node1 -> node2
The structure becomes:
node1 (data=3) -> node2 (data=5) -> null
Now:
print(node2.data) # 5
print(node1.next.data) # 5 (because node1.next points to node2)
3.3 Disconnecting Nodes (Basic Deletion Idea)
If you want to disconnect node1 and node2, assign null to node1.next:
node1.next = null # separate node1 and node2
This is the core idea of deleting a node.
(In an actual implementation, you would also free/delete the removed node.)
4. Head and Tail
When you connect multiple nodes to form a list,
you must know where to start.
- The first node of the list is called the
head. - Optionally, you can also store the last node as
tail.
Head -> Node -> Node -> ... -> Tail
- For traversal, you usually start from
headand
follownextuntil you reachnull. - If you know
tail, then:- You can stop traversal just by checking, “Is the current node the tail?”
- Appending a new node at the end is easy: simply set
tail.nextto the new node.
5. Properties & Time Complexity of a Singly Linked List
A singly linked list supports the following operations:
- Traversal
- You must follow
nextfromheadtotail,
so the time complexity isO(N).
- You must follow
- Insertion/Deletion
- If you already know the previous node of the insertion/deletion position,
you only need to break and reconnect links, which isO(1). - Example: deleting
targetinprev -> target -> next
→prev.next = next
- If you already know the previous node of the insertion/deletion position,
- No Backward Movement
- Because it only has
next, it is one-directional.
You cannot directly move to the previous node (prev) from the current node. - This one-way nature is why it’s called a singly linked list.
- Because it only has
6. Insertion Operations
Here we assume we have separate variables head and (optionally) tail.
6.1 Insert at the Front (Head)
function push_front(x):
new_node = node(x)
new_node.next = head # new node points to the old head
head = new_node # head is updated to the new node
if tail is null: # list was empty before
tail = new_node
- Time complexity:
O(1)
6.2 Insert at the Back (Tail)
Assume we have a tail pointer:
function push_back(x):
new_node = node(x) # new_node.next is null by default
if tail is not null: # list already has nodes
tail.next = new_node
tail = new_node
else: # list was empty
head = new_node
tail = new_node
- Time complexity:
O(1)(because we know the tail)
If you don’t have tail, you must traverse to the end, which is O(N).
6.3 Insert in the Middle (Insert After a Given Node)
Suppose we want to insert after a certain node prev:
function insert_after(prev, x):
if prev is null:
# inserting after “nothing” makes no sense
return
new_node = node(x)
new_node.next = prev.next # new node points to prev's next
prev.next = new_node # prev points to the new node
if prev == tail: # if prev was the tail, update tail
tail = new_node
- Time complexity:
O(1)(assuming we already knowprev)
7. Deletion Operations
The core idea of deletion is
“make the previous node skip the target node and point to the next one.”
7.1 Delete the Front Node (Head)
function pop_front():
if head is null:
return # nothing to delete
removed = head # store the node to delete (free later if needed)
head = head.next # move head to the next node
if head is null: # list became empty
tail = null
- Time complexity:
O(1)
7.2 Delete a Middle or Last Node (Delete After a Given Node)
Delete the node right after prev (i.e., prev.next):
function erase_after(prev):
if prev is null or prev.next is null:
return # nothing to delete
target = prev.next
prev.next = target.next # skip target
if target == tail: # if the deleted node was the tail, update tail
tail = prev
- Time complexity:
O(1)(again, assuming we already knowprev)
7.3 Delete by Value
Now delete the first node with value x.
This requires searching first, so O(N) time in total.
function erase_by_value(x):
if head is null:
return
# 1) head has the value x
if head.data == x:
pop_front()
return
# 2) otherwise: track the previous node while searching
prev = head
curr = head.next
while curr is not null:
if curr.data == x:
prev.next = curr.next
if curr == tail:
tail = prev
break # delete only the first occurrence
prev = curr
curr = curr.next
- Search: worst-case
O(N) - Actual link change:
O(1)
8. One-Line Summary
A singly linked list is a structure where
“nodes of (data + next pointer) are connected in a line.”
Insertion/deletion isO(1)when you know the position (or the previous node),
but searching/finding a position requires walking fromhead, which isO(N),
and movement is only in one direction.
Merging Linked Lists Summary
1. Problem Description
- We have two sorted singly linked lists,
SLL1andSLL2, in ascending order. - We want to merge them into one new linked list,
- And the result must also be in ascending order.
This is essentially the same as merging two sorted arrays,
but the data structure is a linked list instead of an array.
2. Core Idea
- Let
node1start atSLL1.head,
andnode2start atSLL2.head. - At each step:
- Take the smaller value between
node1.dataandnode2.data, and append it to the end of theresultlist. - Move the pointer (
node1ornode2) one step forward in the list from which you took the value.
- Take the smaller value between
- If one list is exhausted,
- Append all remaining nodes from the other list to
result.
- Append all remaining nodes from the other list to
- Because we always append the smaller of the two candidates,
the
resultlist remains sorted in ascending order.
3. Given Pseudocode Skeleton
The problem provides the following skeleton:
function solution(SLL1, SLL2)
set result = empty SLL
node1 = SLL1.head
node2 = SLL2.head
while node1 != null or node2 != null
if node2 == null or (1)
result.insert_end((2))
node1 = node1.next
else
result.insert_end((3))
node2 = node2.next
return result
We need to determine what goes in (1), (2), and (3).
4. Filling in the Missing Parts
4.1 (2) and (3) – Which List Should We Take the Value From?
- The
ifblock uses a value from the first list (SLL1,node1). - The
elseblock uses a value from the second list (SLL2,node2).
So,
(2)→node1.data(3)→node2.data
result.insert_end(node1.data) # (2)
...
result.insert_end(node2.data) # (3)
4.2 (1) – When Should We Use node1’s Value?
The if condition is:
if node2 == null or (1)
So there are two cases where we use node1’s value:
node2 == null
→ The second list has already ended.
All remaining values must come fromnode1.- Both lists still have nodes, and
node1’s value is less than or equal tonode2’s value.
→ To keep the result sorted, we must insertnode1.datafirst.
Therefore, (1) can be written as:
(node1 != null and node1.data <= node2.data)
We include
node1 != nullbecause we must not accessnode1.data
whennode1isnull(assuming short-circuit evaluation).
5. Completed Pseudocode
function solution(SLL1, SLL2)
set result = empty SLL
node1 = SLL1.head
node2 = SLL2.head
while node1 != null or node2 != null
if node2 == null or (node1 != null and node1.data <= node2.data)
# Take from SLL1 when its value is smaller/equal,
# or when SLL2 is already exhausted.
result.insert_end(node1.data)
node1 = node1.next
else
# Otherwise take from SLL2
result.insert_end(node2.data)
node2 = node2.next
return result
If the lengths of the lists are N and M:
- Each node is visited exactly once,
- So the time complexity is
O(N + M).