3.2.2Linear Data Structures

Linked list — singly - node structure, traversal, insert head - tail - middle, delete

2,171 words10 min readdifficulty · medium5 backlinks

1. The Node — the atom of the list

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None      # null until linked
 
class LinkedList:
    def __init__(self):
        self.head = None      # empty list
Figure — Linked list — singly -  node structure, traversal, insert head - tail - middle, delete

2. Traversal — walking the chain

def traverse(self):
    cur = self.head          # start at front door
    while cur is not None:   # null = end of chain
        print(cur.data)
        cur = cur.next       # hop to next box

3. Insertion

The whole skill is: create the node first, wire its next first, then change the incoming pointer last. Reverse that order and you cut the chain.

3a. Insert at HEAD — O(1)O(1)

def insert_head(self, data):
    new = Node(data)
    new.next = self.head   # step 1: grab old front  — Why? so we don't lose the chain
    self.head = new        # step 2: move front door — Why? new is now first

3b. Insert at TAIL — O(n)O(n) (or O(1)O(1) with a tail pointer)

def insert_tail(self, data):
    new = Node(data)
    if self.head is None:        # empty list special case
        self.head = new          # Why? no node to attach to; new becomes head
        return
    cur = self.head
    while cur.next is not None:  # Why .next here? we WANT the last node, not None
        cur = cur.next
    cur.next = new               # attach after last node

3c. Insert in MIDDLE (after position k) — O(k)O(k)

def insert_after(self, k, data):   # insert after the k-th node (0-indexed)
    cur = self.head
    for _ in range(k):             # Why k hops? to land ON node k
        if cur is None:
            raise IndexError("position out of range")
        cur = cur.next
    new = Node(data)
    new.next = cur.next            # step 1: new -> old successor
    cur.next = new                 # step 2: cur -> new

4. Deletion

def delete(self, value):
    cur = self.head
    if cur is None:
        return                       # empty
    if cur.data == value:            # deleting the head
        self.head = cur.next         # Why? front door now skips old head
        return
    prev = self.head
    cur = self.head.next
    while cur is not None:
        if cur.data == value:
            prev.next = cur.next     # unlink: prev skips cur
            return
        prev = cur                   # Why advance BOTH? keep prev one behind
        cur = cur.next

Recall Feynman: explain to a 12-year-old

Imagine a treasure hunt. Each clue card has a treasure on it AND tells you where the next card is hidden. You only know where the first card is (that's head). The last card says "no more cards" (that's null). To read all treasures you must follow card-to-card — you can't teleport to card #7. To add a card, you write it, point it to the card the previous one was pointing to, then make the previous one point to your new card. To remove a card, you just make the card before it point to the card after it — the removed card is now lost in the woods. That re-pointing is super cheap; that's the whole magic of linked lists.


Flashcards

What two fields does a singly-linked-list node contain?
data (the value) and next (pointer to the next node, or null at the end).
Why is random index access O(n)O(n) in a linked list but O(1)O(1) in an array?
An array uses base + i*size arithmetic; a linked list only knows each node's successor, so you must walk from head.
What is the correct traversal loop condition?
while cur is not None (process node, then cur = cur.next).
Why does while cur.next is not None fail as a traversal condition?
It skips the last node and crashes on an empty list (None.next).
Give the two ordered steps to insert at head.
1) new.next = head 2) head = new. Reversing them loses the old list.
Why is insert-at-tail O(n)O(n) with only a head pointer?
You must walk to the node whose next is null before attaching.
Two steps to insert new after node p?
1) new.next = p.next 2) p.next = new.
Why must deletion track the previous node in a singly list?
To unlink you set prev.next = cur.next, but a singly list has no backward pointer, so prev must be carried.
How do you delete the head node?
head = head.next.
What happens to a node after nothing points to it?
It becomes unreachable and is garbage-collected / freed.

Connections

  • Arrays — contiguous memory & O(1) indexing (the trade-off opposite)
  • Doubly Linked List (adds a prev pointer → backward walk, easier delete)
  • Stack using Linked List (push/pop = insert/delete at head, O(1)O(1))
  • Queue using Linked List (needs head + tail pointers)
  • Pointers and References (the underlying mechanism)
  • Big-O Notation (why insert-head beats array insert-front)

Concept Map

indexes via base+i*size

gives up random access

made of

holds

holds

null marks

entry point

lose it means

walk via next

loop while cur not null

re-point 2 arrows

at head

wire next first

Array contiguous

Random access O 1

Linked List

Node

data field

next pointer

End of list

head pointer

List becomes garbage

Traversal O n

Visit each node

Insert or Delete

O 1

Avoid cutting chain

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Socho ek treasure hunt chal rahi hai. Har card pe ek value likhi hai aur saath me likha hai ki agla card kahan chhupa hai. Yahi ek node hai: usme data (value) aur next (agle node ka address) hota hai. Aapko sirf pehle card ka pata hota hai — usse hum head bolte hain. Aakhri card pe likha hota hai "ab koi card nahi" — yeh null hai. Array me to aap seedhe item number 7 pe jump kar sakte ho (base + i*size), par linked list me yeh teleport nahi hota; aapko card-by-card chalna padta hai, isliye traversal aur search dono O(n)O(n) hote hain.

Magic tab dikhta hai jab insert ya delete karna ho. Array me beech me daalna ho to baaki sab elements shift karne padte hain — mehnga. Linked list me bas do arrows badalne hote hain. Insert ka golden rule: pehle naye node ka next set karo (new.next = purana), uske baad hi head ya prev.next ko naye node pe le jao. Ulta kiya to chain toot jaati hai aur poora aage ka list kho jaata hai.

Delete me ek catch hai: singly list me peeche dekhne ka koi pointer nahi hai. Kisi node ko hatane ke liye uske pehle wale node ko chahiye, taaki prev.next = cur.next karke beech wale node ko skip kar do. Isliye chalte waqt hamesha prev (trailing pointer) saath rakho. Aur head delete karna ho to special case: bas head = head.next.

Yaad rakho: insert head = O(1)O(1) (sabse sasta), insert tail sirf head se = O(n)O(n) (end tak chalna padta hai), aur agar aapke paas already wo node ho jiske baad insert karna hai to wo O(1)O(1). Exam aur interview dono me yeh "wire-then-redirect" pattern baar-baar aata hai — ratta mat maaro, logic samjho.

Go deeper — visual, from zero

Test yourself — Linear Data Structures

Connections