← Linked list lesson
Lab

Linked list

type ListNode<T> = { value: T; prev: ListNode<T> | null; next: ListNode<T> | null };

class LinkedList<T> {
  head: ListNode<T> | null = null;
  tail: ListNode<T> | null = null;

  push(value: T): ListNode<T> {
    const node: ListNode<T> = { value, prev: this.tail, next: null };
    if (this.tail) this.tail.next = node;
    else this.head = node;
    this.tail = node;
    return node;
  }

  find(value: T): ListNode<T> | null {
    for (let node = this.head; node; node = node.next) {
      if (node.value === value) return node;
    }
    return null;
  }

  insertAfter(anchor: ListNode<T>, value: T): ListNode<T> {
    const node: ListNode<T> = { value, prev: anchor, next: anchor.next };
    if (anchor.next) anchor.next.prev = node;
    else this.tail = node;
    anchor.next = node;
    return node;
  }

  moveAfter(node: ListNode<T>, anchor: ListNode<T>): void {
    if (node === anchor || anchor.next === node) return;
    // Unhook from the old neighbors.
    if (node.prev) node.prev.next = node.next;
    else this.head = node.next;
    if (node.next) node.next.prev = node.prev;
    else this.tail = node.prev;
    // Hook in after the anchor.
    node.prev = anchor;
    node.next = anchor.next;
    if (anchor.next) anchor.next.prev = node;
    else this.tail = node;
    anchor.next = node;
  }

  values(): T[] {
    const out: T[] = [];
    for (let node = this.head; node; node = node.next) out.push(node.value);
    return out;
  }
}

const jobs = new LinkedList<string>();
const pocket = jobs.push('Pocket guide');
jobs.push('Annual report');
jobs.push('Poetry collection');

// The caller has a name, not a node: find walks from the head to get one.
const annual = jobs.find('Annual report');
if (!annual) throw new Error('Annual report is not on the worklist');
const repair = jobs.insertAfter(annual, 'Repair manual');
console.log(jobs.values().join(' → '));

jobs.moveAfter(repair, pocket);
console.log(jobs.values().join(' → '));
Build the worklistAwaiting the recording
Nodes appear when their values and links are recorded.
next previous
Forward walk · recorded links

Not observed yet

Link changes seen0

Same badge, same job. Arrows follow recorded references. Counters describe observations, not elapsed time.

Play or step to inspect the recorded links.