Singly Linked List
A Singly Linked List is a linear data structure where each element (node) contains data and a pointer to the next node. Unlike arrays, linked lists don't have fixed sizes and allow efficient insertion/deletion at any position.
The list maintains a head pointer that points to the first node. The last node's next pointer is null, indicating the end of the list. This structure provides O(1) insertion/deletion at the head but O(n) access time for arbitrary elements.
Singly linked lists are fundamental building blocks for more complex data structures like stacks, queues, and adjacency lists for graphs.
Key Property: Each node contains data and a single pointer to the next node, forming a unidirectional chain.
Basic Operations
Operation | Time Complexity | Description |
---|---|---|
Insertion at Head | O(1) | Add new node at beginning by updating head pointer |
Insertion at Tail | O(n) | Traverse to end and add new node (O(1) with tail pointer) |
Deletion at Head | O(1) | Remove first node by updating head pointer |
Deletion by Value | O(n) | Traverse list to find and remove specific node |
Search | O(n) | Traverse list to find element |
Access by Index | O(n) | Traverse list until reaching desired position |
Implementation
class Node { constructor(data) { this.data = data; this.next = null; }}class SinglyLinkedList { constructor() { this.head = null; this.size = 0; } // Check if list is empty isEmpty() { return this.head === null; } // Insert at head insertFirst(data) { const newNode = new Node(data); newNode.next = this.head; this.head = newNode; this.size++; }
Insertion at Head
- 1. Create new node with given data
- 2. Set new node's next to current head
- 3. Update head pointer to new node
- 4. Increment list size counter
Deletion Operations
- 1. Check if list is empty (head === null)
- 2. If deleting head, update head to head.next
- 3. For middle deletion, find previous node and update its next pointer
- 4. Decrement list size counter
- 5. Return deleted data (if needed)
Operation Visualization
Operation | List State |
---|---|
Initialization | head → null |
insertFirst(10) | head → [10|•] → null |
insertFirst(20) | head → [20|•] → [10|•] → null |
insertLast(30) | head → [20|•] → [10|•] → [30|•] → null |
deleteFirst() | head → [10|•] → [30|•] → null |
delete(30) | head → [10|•] → null |
Pros and Cons
Advantages
- Dynamic size - grows as needed
- Efficient insertion/deletion at head
- No memory waste (only allocates needed nodes)
Limitations
- No random access - must traverse from head
- Extra memory for next pointers
- Not cache-friendly (nodes scattered in memory)
Applications
- Implementing stacks and queues
- Memory management systems
- Undo functionality in software
- Hash table collision handling
- Polynomial representation and arithmetic
- Browser history navigation
Note: Singly linked lists are preferred when you need constant-time insertions/deletions at the beginning and don't require backward traversal.