Linked Lists & Pointer Operations
Understand how nodes connect, how pointers move, and how linked lists change through operations.
- 01Cover
- 02Array vs. Linked List
- 03Anatomy of a Node
- 04Building the List
- 05Insert at Beginning
- 06Insert at End
- 07Insert at a Position
- 08Delete from Beginning
- 09Delete at End
- 10Delete at a Position
- 11Traversal
- 12Searching
- 13Edge Cases
- 14C++ Implementation
- 15Complete Walkthrough
- 16Predict the Output
- 17Key Takeaways
Array vs. Linked List
arr[i]By following nextInsert 15 at index 1 — press “Animate Insertion”.
Anatomy of a Node
intNode*Node*Node*Node*Building the List
Two pointers define the whole list. Every insertion and deletion ahead is just restoring these three rules.
nullptr only when emptynullptr only when emptynext is always nullptrInsert at Beginning
Create the node: allocate a node holding the new value; its next starts as nullptr.
Link forward first: point the new node at the current first node (10).
Move the entry point: head now marks node 5 as the new front.
Special case: inserting into an empty list must also set tail.
Insert at End
If the list is empty: the new node becomes both the first and the last node.
Link the last node forward: the current tail (30) now points at the new node.
Advance tail: tail now identifies the new final node (40).
Insert at a Position
Find the predecessor: walk pos - 1 steps from head; temp stops at node 10.
Link forward first: connect node 15 to node 20 before touching node 10.
Then re-link the predecessor: node 10 now points at node 15.
Front insertion repeats the begin case; an out-of-range position stops at nullptr.
newNode->next changed — node 10 still points at 20.Delete from Beginning
Keep a handle: save the node being removed (5) so it can be freed later.
Advance head: head moves to node 10, which becomes the new first node.
Release the memory: free node 5, which is now unreachable from the list.
Last node removed: if the list becomes empty, tail must be cleared too.
Delete at End
Find the predecessor: advance temp until the next node is the tail; temp stops at 20.
Free the last node: release node 30.
Terminate the chain: node 20's next now marks the end.
Move tail: tail now identifies node 20 as the final node.
Delete at a Position
Find the predecessor: walk pos - 1 steps from head; temp stops at node 15, the node before position 3.
Identify the target: the node to remove is node 20.
Bypass the target: point node 15 directly at node 25.
Free the node: release node 20 and, if it was the tail, move tail back to temp.
delete toDelete frees it.List Traversal
List: 10 →20 →30 →NULLSearching the List
Successful search: on the list 5 → 10 → 15 → 20 → 30 the comparisons run 5, then 10, then 15 — the search reports the value and stops.
Unsuccessful search: every node is compared, the pointer finally reaches nullptr, and the key is reported as missing.
Critical Edge Cases
Every method must guard the boundaries: an empty list, a single node, the first position, and positions that do not exist.
head crashes.if (head == nullptr) return;tail is left dangling.head = tail = nullptr;pos - 1 node.if (pos == 1) { … }temp == nullptrtemp != nullptr, so the walk cannot dereference a null node.C++ Implementation
The LinkedList class keeps a single head and tail; every method you have seen operates on the very same chain.
Two private pointers: they are the only references into the list and are managed only by the class.
Start empty: the constructor guarantees a well-defined empty state before any operation runs.
insertAtBeginninginsertAtEndinsertAtPositiondeleteFromBeginningdeleteAtEnddeleteAtPositiontraversesearchnew allocates each node and delete releases it.Complete Walkthrough
| Call | List after | Output printed |
|---|---|---|
| insertAtEnd(10)(20)(30) | 10 → 20 → 30 | List: 10 → 20 → 30 → NULL |
| insertAtBeginning(5) | 5 → 10 → 20 → 30 | List: 5 → 10 → 20 → 30 → NULL |
| insertAtPosition(15, 3) | 5 → 10 → 15 → 20 → 30 | List: 5 → 10 → 15 → 20 → 30 → NULL |
| search(15) | unchanged | 15 found in the list. |
| search(99) | unchanged | 99 not found in the list. |
| deleteFromBeginning() | 10 → 15 → 20 → 30 | Deleted 5 from beginning. |
| deleteAtEnd() | 10 → 15 → 20 | Deleted 30 from end. |
| deleteAtPosition(2) | 10 → 20 | Deleted 15 from position 2. |
List: 10 -> 20 -> 30 -> NULL
=== Insert at Beginning ===
List: 5 -> 10 -> 20 -> 30 -> NULL
=== Insert at Position 3 ===
List: 5 -> 10 -> 15 -> 20 -> 30 -> NULL
=== Search ===
15 found in the list.
99 not found in the list.
=== Delete from Beginning ===
Deleted 5 from beginning.
List: 10 -> 15 -> 20 -> 30 -> NULL
=== Delete from End ===
Deleted 30 from end.
List: 10 -> 15 -> 20 -> NULL
=== Delete from Position 2 ===
Deleted 15 from position 2.
List: 10 -> 20 -> NULL
Predict the Output
Trace the three calls by hand before revealing the answer. Use only the pointer rules already covered.
5 → 10 → 20 → 305 → 10 → 15 → 20 → 305 → 10 → 15 → 20Key Takeaways
delete.nullptr.nullptr, marking the end.insertAtBeginning, deleteFromBeginning and insertAtEnd work on the ends directly.deleteAtEnd — links point one way, so the walk starts at head.insertAtPosition and deleteAtPosition walk up to the position, then rewire.traverse and search follow next to the end.