Trees, heaps, hashing & graph traversal
Seven self-contained experiments, each a genuinely working visualizer built in plain JavaScript — no libraries. Every operation mutates the real data structure and animates the path it takes. Pick an experiment on the left, then move through Aim, Theory, Procedure, the live Simulation, a graded Self-assessment, and References.
1 · Binary search tree
A binary search tree is a binary tree in which, for every node, all keys in its left subtree are smaller and all keys in its right subtree are larger. This ordering lets every operation discard half the remaining tree at each step — provided the tree stays balanced.
To search for a key, start at the root and go left when the target is smaller, right when larger, stopping on equality or a null link. Insertion follows the same path and attaches a new leaf where the search fell off. Deletion has three cases: a leaf is simply removed; a node with one child is spliced out; a node with two children is replaced by its in-order successor (the smallest key in its right subtree).
Traversals visit every node. In-order (left, node, right) emits keys in ascending order. Pre-order (node, left, right) is useful for copying a tree; post-order (left, right, node) for deleting one. Operations cost O(h) where h is the height — about log n for a balanced tree, but up to n for a degenerate chain.
- Open the Simulation tab. A starter tree is already built.
- Type a number and press Insert. Watch the green path descend from the root to the new leaf.
- Press Search on an existing key — the path lights up and the node flashes. Search a missing key to see the path end at null.
- Press Delete on a node with two children and observe it being replaced by its in-order successor.
- Read the three traversal strings; verify the in-order list is sorted. Check the reported height and the balanced? flag.
- Use Random and Reset, and the speed slider, to explore.
BST balanced
Pre-order: --
Post-order: --
Operations
- Cormen, Leiserson, Rivest & Stein — Introduction to Algorithms, Ch. 12 (Binary Search Trees). MIT Press.
- Sedgewick & Wayne — Algorithms, 4th ed., Sec. 3.2. Addison-Wesley.
- Virtual Labs (IIT) — Data Structures: Binary Search Tree, ds1-iiith.vlabs.ac.in.
2 · AVL self-balancing tree
An AVL tree is a binary search tree that keeps itself height-balanced. The balance factor of a node is the height of its left subtree minus that of its right subtree. The invariant is that this factor is always one of minus-one, zero, or plus-one. Whenever an insertion or deletion pushes a node out of range, the tree rebalances with rotations.
There are four cases, named by the shape of the offending path. LL (left-left, factor plus-two with left child leaning left) needs one right rotation. RR needs one left rotation. LR needs a left rotation on the child then a right rotation on the node; RL is the mirror. A rotation re-parents three subtrees in constant time while preserving the BST ordering.
rebalance if balance < -1 or balance > 1
Because the height of an AVL tree with n keys is at most about 1.44·log₂(n), search, insert and delete are all guaranteed O(log n) — the degenerate chains a plain BST can form never occur.
- Open the Simulation tab and press Reset to start empty.
- Insert keys 10, 20, 30 in order. After 30, the tree detects an RR imbalance and performs a left rotation — watch 20 rise to the root.
- Insert 10, 30, 20 instead to trigger an LR double rotation. The log names every rotation as it happens.
- Read each node's balance factor drawn beside it; confirm none exceeds plus-or-minus one.
- Delete keys and watch deletions also rebalance. Compare the AVL height with what a plain BST would reach for the same sequence.
AVL tree AVL ok
Each node shows its balance factor in amber. A factor outside minus-one to plus-one triggers a rotation.
Operations
- Adelson-Velsky & Landis — An algorithm for the organization of information (1962), the original AVL paper.
- Cormen et al. — Introduction to Algorithms, Problem 13-3 (AVL trees). MIT Press.
- Weiss, M. A. — Data Structures and Algorithm Analysis in C++, Sec. 4.4. Pearson.
3 · Binary heap (min / max)
A binary heap is a complete binary tree stored compactly in an array: the node at index i has children at 2i+1 and 2i+2 and parent at (i-1)/2 (integer division). The heap property says every parent dominates its children — in a min-heap the parent is no larger, so the smallest key sits at the root; in a max-heap the largest sits at the root.
Insertion appends the new key at the end and sifts it up, swapping with its parent while the property is violated. Extract-root removes the top, moves the last element to the root, and sifts it down, swapping with its smaller (or larger) child until order is restored. Both touch only one root-to-leaf path, so both cost O(log n).
Build-heap from an arbitrary array sifts down every internal node from the last parent up to the root; a careful accounting shows this is O(n), not O(n log n). Heaps are the engine behind priority queues and heapsort.
- Open the Simulation tab. Toggle between Min and Max heap.
- Insert a key and watch it bubble up the highlighted path until the parent dominates it.
- Press Extract root; the last leaf jumps to the top and sinks down, swapping with the smaller (min-heap) child each step.
- Compare the tree view with the array view below it — index i, child 2i+1, 2i+2 line up exactly.
- Press Build-heap on a fresh random array and watch heapify run from the last parent upward.
Heap min-heap
Operations
- Cormen et al. — Introduction to Algorithms, Ch. 6 (Heapsort). MIT Press.
- Williams, J. W. J. — Algorithm 232: Heapsort. Communications of the ACM, 1964.
- Virtual Labs (IIT) — Data Structures: Heaps, ds1-iiith.vlabs.ac.in.
4 · Hash table & collisions
A hash table stores keys in an array of m buckets, placing a key at index h(k) = k mod m. When two keys hash to the same bucket a collision occurs, and the resolution scheme decides what happens next.
Separate chaining keeps a linked list at each bucket; colliding keys are appended. Search scans only the chain at h(k). Linear probing is open addressing: on a collision it scans forward — h(k), h(k)+1, h(k)+2, modulo m — for the next free slot. It is cache-friendly but suffers primary clustering as runs of occupied slots grow.
chaining: expected probes ≈ 1 + α
linear probing: probes grow sharply as α → 1
Deletion under linear probing must leave a tombstone rather than a true empty, otherwise it would break the probe chain for later keys. Average operations are O(1) at low load; performance degrades as α approaches one.
- Open the Simulation tab. Choose Chaining or Linear probing.
- Insert keys; the chosen bucket flashes. Insert keys that share k mod m to force a collision and watch the resolution differ between the two modes.
- Read the load factor and collisions counters. Push the load factor up and see probe counts climb under linear probing.
- Search a key — the probe sequence lights up slot by slot. Delete under linear probing and note the tombstone marker.
- Change the table size and Reset to study how m affects clustering.
Hash table chaining
h(k) = k mod 11. Buckets shown left-to-right, top-to-bottom. Tombstones (deleted, probing) appear as dim red.Operations
- Cormen et al. — Introduction to Algorithms, Ch. 11 (Hash Tables). MIT Press.
- Knuth, D. E. — The Art of Computer Programming, Vol. 3, Sec. 6.4. Addison-Wesley.
- Virtual Labs (IIT) — Data Structures: Hashing, ds1-iiith.vlabs.ac.in.
5 · Stack, queue & circular queue
A stack is last-in-first-out: push adds to the top, pop removes from the top. It models recursion, undo, and expression evaluation. A queue is first-in-first-out: enqueue adds at the rear, dequeue removes from the front — the model for buffering and scheduling.
A naive array queue wastes space as the front advances. A circular queue fixes this: front and rear indices wrap with modulo arithmetic, reusing slots a plain queue would abandon. With capacity C, the rear advances as (rear+1) mod C. Overflow is signalled when the structure is full; underflow when a pop or dequeue is attempted on an empty structure.
circular queue empty: front == -1
All operations — push, pop, enqueue, dequeue — are O(1): they touch only the top or the two end pointers, never the interior.
- Open the Simulation tab and pick a structure: Stack, Queue, or Circular queue.
- Push or enqueue values and watch where each lands — top for a stack, rear for a queue.
- Pop or dequeue and confirm the order: the stack returns the newest, the queue the oldest.
- Fill a circular queue to capacity, then keep adding to trigger an overflow warning; empty it fully to trigger underflow.
- In circular mode, dequeue a few then enqueue more and watch the rear pointer wrap back to slot 0.
Linear structures empty
Operations
- Cormen et al. — Introduction to Algorithms, Sec. 10.1 (Stacks and Queues). MIT Press.
- Sedgewick & Wayne — Algorithms, 4th ed., Sec. 1.3. Addison-Wesley.
- Virtual Labs (IIT) — Data Structures: Stacks and Queues, ds1-iiith.vlabs.ac.in.
6 · Linked list (singly / doubly)
A linked list stores each element in a node that holds a value and a pointer to the next node; the list is reached through a head reference. Unlike an array, nodes need not be contiguous, so insertion and deletion are pointer rewires rather than bulk shifts — but there is no random access, so reaching position k costs O(k).
In a singly linked list each node points only forward. Insertion at the head is O(1): the new node points to the old head and becomes the head. Insertion at the tail or a position requires walking there first. Deletion splices a node out by linking its predecessor to its successor.
A doubly linked list adds a prev pointer, enabling backward traversal and O(1) deletion of a known node, at the cost of an extra pointer per node. Reversal of a singly list walks once, flipping each next pointer to the previous node — an O(n), O(1)-extra-space classic.
- Open the Simulation tab and choose Singly or Doubly.
- Insert at head and at tail; watch the new node's pointer attach and the head or tail update.
- Insert at position k — the traversal walks k nodes (highlighted) before splicing in the new node.
- Search a value and watch the linear scan. Delete a node and see its neighbours re-link across the gap.
- Press Reverse and follow the pointers flipping one node at a time; confirm the order is inverted.
Linked list singly
Operations
- Cormen et al. — Introduction to Algorithms, Sec. 10.2 (Linked Lists). MIT Press.
- Sedgewick & Wayne — Algorithms, 4th ed., Sec. 1.3 (Linked structures). Addison-Wesley.
- Virtual Labs (IIT) — Data Structures: Linked Lists, ds1-iiith.vlabs.ac.in.
7 · Graph traversal — BFS / DFS
A graph is a set of vertices joined by edges. The two canonical ways to explore one from a source differ only in the order they pull vertices from their frontier. Breadth-first search uses a queue (FIFO): it visits the source, then all neighbours, then their neighbours — expanding outward in rings of increasing distance. On an unweighted graph BFS finds shortest paths in edges.
Depth-first search uses a stack (LIFO, often the call stack): it plunges as deep as possible along one branch before backtracking. DFS underlies cycle detection, topological sort, and connectivity.
DFS: frontier = stack (LIFO) → deep-first exploration
both: O(V + E) with adjacency lists
Each search marks vertices as visited to avoid revisiting, and records a discovery (tree) edge when it first reaches a vertex. Those edges form the traversal tree drawn in green. Both run in O(V + E) time.
- Open the Simulation tab. A sample graph loads; click empty space to add a vertex, drag between two vertices to add an edge.
- Pick a source vertex from the dropdown (or click a vertex while in Source mode).
- Press Run BFS. The queue contents are shown live; visited vertices fill in order and tree edges turn green.
- Press Reset run, then Run DFS and compare the order — note how DFS dives deep while BFS spreads in layers.
- Read the final visiting order string and the number of tree edges (always V minus components for the reached part).
Graph view
Frontier (queue / stack): --
Build & run
- Cormen et al. — Introduction to Algorithms, Ch. 22 (Elementary Graph Algorithms). MIT Press.
- Tarjan, R. E. — Depth-first search and linear graph algorithms. SIAM J. Computing, 1972.
- Virtual Labs (IIT) — Data Structures: Graph Traversals, ds1-iiith.vlabs.ac.in.