Kazi Rahamatullah
Kazi Rahamatullah
AboutProjectsBlogContact
UsesBooks
ResumeView CV
Kazi Rahamatullah

© Copyright 2026 Kazi Rahamatullah

AboutProjectsBlogBooksUses
Twitter/XGitHubProduct HuntCodeSandbox
Back to Blog
DSALinked ListsOperationsAlgorithms

Linked List Operations — Insert, Delete & Search Visualized

Master linked list operations — prepend O(1), append, delete, search O(n), pointer rewiring, full implementation with function call output, and interactive step visualizer.

Jul 4, 20264 min read

Introduction

Linked list operations boil down to rewiring pointers — prepend at head in O(1), search and delete in O(n) unless you hold a direct node reference. This guide walks through each operation with code and an interactive visualizer.

Quick index

#Section
1Operation overview
2Interactive visualizer
3Full implementation
4Complexity table
5Real-life examples

1. Operation overview

OperationTimeKey idea
PrependO(1)new.next = head; head = new
AppendO(n)*Walk to tail, link new node
DeleteO(n)Find predecessor, skip target
SearchO(n)Linear scan from head

*O(1) append if tail pointer is maintained.

Back to index


2. Interactive visualizer

Linked List Operations

Prepend, append, delete, and search — step through pointer rewiring in O(1) and O(n) cases.

Prepend

head
ref→
5
next
n0
→
10
next
n1
→
20
next
n2
→
null
↑ tail

Insert at head — O(1). New node.next = head; head = new node.

Prepend O(1)

list.prepend(5)→ [5, 10, 20]
node.next = head; head = node// rewire head pointer

Cheapest insert — no traversal needed.

Prepend

O(1)

Append*

O(n)

Delete

O(n)

Search

O(n)

Tip

Step 5 (Full demo) shows every function call with output on the right — the same format as the code block below.

Back to index


3. Full implementation

js
class Node {
  constructor(value) {
    this.value = value
    this.next = null
  }
}
 
class LinkedList {
  constructor() {
    this.head = null
    this.tail = null
  }
 
  prepend(val) {
    const node = new Node(val)
    if (!this.head) this.tail = node
    node.next = this.head
    this.head = node
  }
 
  append(val) {
    const node = new Node(val)
    if (!this.head) {
      this.head = this.tail = node
      return
    }
    this.tail.next = node
    this.tail = node
  }
 
  delete(val) {
    if (!this.head) return
    if (this.head.value === val) {
      this.head = this.head.next
      if (!this.head) this.tail = null
      return
    }
    let cur = this.head
    while (cur.next && cur.next.value !== val) cur = cur.next
    if (cur.next) {
      cur.next = cur.next.next
      if (!cur.next) this.tail = cur
    }
  }
 
  search(val) {
    let cur = this.head
    while (cur) {
      if (cur.value === val) return cur
      cur = cur.next
    }
    return null
  }
 
  toArray() {
    const out = []
    let cur = this.head
    while (cur) {
      out.push(cur.value)
      cur = cur.next
    }
    return out
  }
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
const list = new LinkedList()
 
list.prepend(10) // → toArray(): [10]
list.prepend(5) // → toArray(): [5, 10]
list.append(20) // → toArray(): [5, 10, 20]
list.append(30) // → toArray(): [5, 10, 20, 30]
 
list.delete(10) // → toArray(): [5, 20, 30]
list.search(20) // → Node { value: 20 }
list.search(99) // → null
 
list.toArray() // → [5, 20, 30]

Back to index


4. Complexity table

OperationSingly (no tail)Singly + tailDoubly + tail
PrependO(1)O(1)O(1)
AppendO(n)O(1)O(1)
Delete headO(1)O(1)O(1)
Delete arbitraryO(n)O(n)O(1)*

*Doubly: O(1) delete if you hold the node reference.

Interview Answer

"How do you detect a cycle in a linked list?"

Floyd's tortoise and hare — slow moves 1 step, fast moves 2. If they meet, a cycle exists. Also used to find the cycle start.

Back to index


5. Real-life examples

OperationReal app example
PrependAdd new notification to top of feed — O(1), no re-render of entire list
AppendAdd message to chat thread end — O(1) with tail pointer
DeleteRemove completed todo item — rewire previous node's next
SearchFind user in unsorted follower list — O(n) scan
Insert afterAdd slide after current in presentation editor

Todo app feed

Prepend new tasks to top — O(1) with no array shifting.

head
ref→
Buy groceries
next
n0
→
null
↑ tail

New notification at top — O(1) prepend.

Real-world implementation

class Node { constructor(val) { this.val = val; this.next = null } }
class TodoList {
  constructor() { this.head = null; this.tail = null }
  prepend(task) {
    const n = new Node(task)
    if (!this.head) this.tail = n
    n.next = this.head; this.head = n
  }
  append(task) {
    const n = new Node(task)
    if (!this.head) { this.head = this.tail = n; return }
    this.tail.next = n; this.tail = n
  }
  delete(id) {
    if (!this.head) return false
    if (this.head.val.id === id) { this.head = this.head.next; if (!this.head) this.tail = null; return true }
    let cur = this.head
    while (cur.next && cur.next.val.id !== id) cur = cur.next
    if (!cur.next) return false
    cur.next = cur.next.next; if (!cur.next) this.tail = cur; return true
  }
  toArray() { const out = []; let c = this.head; while (c) { out.push(c.val.text); c = c.next } return out }
}

Full working code for the scenario above.

Function calls with output

// ── Function calls with output ──
const list = new TodoList()
list.prepend({ id:1, text:"Buy groceries" })→ ["Buy groceries"]

Side output shows return value after each call — step through to trace execution.

Back to index


Summary

Prepend is the linked list superpower — O(1) with no shifting. Everything else usually needs a walk from head.

Next reads: Linked Lists Fundamentals · DSA Arrays for the contrast

Share this article

XLinkedInFacebook
Kazi Rahamatullah

Written by

Kazi Rahamatullah

FullStack Developer

X / TwitterGitHubLinkedIn

Subscribe to my newsletter

Stay up to date and get notified when I share new contents.

No spam ever, unsubscribe anytime