Arrays usually get all the love. They're easy to use, built into every language, and great for most tasks.
But there’s another data structure that quietly powers a lot of efficient solutions: the linked list.
It’s not about speed for direct access — it’s about flexibility, efficient insertions, and being the foundation for structures like stacks, queues, and even graphs.
Let’s give it the spotlight it deserves.
🤔 What Is a Linked List?
A linked list is a linear data structure made up of nodes.
Each node holds:
- A value
- A reference (or pointer) to the next node
A simple representation:
[10] → [20] → [30] → null
Unlike arrays, elements in a linked list are not stored in contiguous memory. This makes linked lists:
- More memory flexible
- Ideal for fast insertions and deletions
- Slower for direct access to elements by index
🛠️ Use Cases: When Are Linked Lists Useful?
Use a linked list when:
- You need dynamic memory allocation
- You perform frequent insertions/deletions
- You don't require constant-time random access (
O(1)
index lookup)
Some real-world applications:
- Undo/redo functionality in editors
- Browser history
- Queues and stacks
- Hash table chaining (collision resolution)
🧠 Types of Linked Lists
- Singly Linked List – Each node points to the next
- Doubly Linked List – Each node points to both next and previous
- Circular Linked List – Last node points back to the first node
🧪 Let’s Build a Simple Linked List in JavaScript
Here’s a minimal implementation of a singly linked list:
// Each node in the linked list holds a value and a pointer to the next node
class Node {
constructor(value) {
this.value = value; // Store the actual data
this.next = null; // Pointer to the next node (default: null)
}
}
// LinkedList class manages the overall list
class LinkedList {
constructor() {
this.head = null; // Start with an empty list
}
// Adds a new node at the end of the list
append(value) {
const newNode = new Node(value);
// If list is empty, set head to the new node
if (!this.head) {
this.head = newNode;
return;
}
// Otherwise, traverse to the end of the list
let current = this.head;
while (current.next) {
current = current.next;
}
// Link the last node to the new node
current.next = newNode;
}
// Prints out the list in a readable format
print() {
let current = this.head;
let output = '';
// Traverse and build the output string
while (current) {
output += `[${current.value}] → `;
current = current.next;
}
output += 'null'; // End of the list
console.log(output);
}
}
// Example usage
const list = new LinkedList();
list.append(10);
list.append(20);
list.append(30);
list.print(); // Output: [10] → [20] → [30] → null
⏱️ Time Complexity Overview
Operation | Time Complexity |
---|---|
Insert at Head | O(1) |
Insert at Tail | O(n) |
Search | O(n) |
Delete Node | O(n) |
Access by Index | O(n) |
⚖️ Pros & Cons
✅ Pros:
- Efficient insertions/deletions
- Dynamic memory use (no resizing)
- Great for stacks, queues, etc.
❌ Cons:
- Slower access time (O(n) for index)
- Uses extra memory (pointers)
- More complex to implement than arrays
🧵 TL;DR
- A Linked List is a dynamic, node-based data structure.
- It’s ideal when you don’t know the final size of your collection.
- Although not as fast for access, it excels in insertions and deletions.
- It lays the foundation for many advanced data structures.
Thanks for reading! 🙌
If you're enjoying the series, feel free to follow me here or check out my YouTube channel for more hands-on dev content.
Top comments (0)