Skip to content

Repository files navigation

Sorting Algorithms Visualizer

A web app that visualizes sorting algorithms in real time using animated bar charts. Watch a single algorithm step through its work with synced pseudocode, or race all nine side-by-side on the same input. Built with React 19, TypeScript, React Router 7, and Bootstrap 5.

Two views

Route View What it does
/single-algorithm-visualizer Single Algorithm Visualizer Run one algorithm at a time with full playback controls (pause / resume / scrub / restart), a pseudocode panel synced to the current step, and swap / comparison tallies.
/algorithm-comparison Algorithm Comparison Run all nine algorithms on the same generated array in side-by-side mini-charts, with a master scrub + pause/resume/restart that drives every panel at once.

The two screens cross-link to each other; / redirects to the single-algorithm view.

Algorithms

Algorithm Time complexity Notes
Bubble Sort O(n²) Repeatedly swaps adjacent out-of-order elements
Selection Sort O(n²) Finds the minimum and places it at the front each pass
Insertion Sort O(n²) Builds a sorted prefix one element at a time
Merge Sort O(n log n) Divide-and-conquer; stable; merges in a buffer
Quick Sort O(n log n) avg, O(n²) worst Lomuto partition, recursive
Heap Sort O(n log n) Builds a max heap and repeatedly extracts the maximum
Shell Sort ~O(n^1.5) Insertion sort over halving gap sequence (n/2)
Tim Sort O(n log n) Hybrid: insertion-sort runs of 32, then merge
Intro Sort O(n log n) Hybrid: quicksort, falling back to heapsort (depth limit) and insertion sort (small ranges)

Input patterns

The starting array can be generated as Random, Already sorted, Reversed, Nearly sorted (sorted with ~10% of values randomized), or Many duplicates (drawn from four distinct values). Values range from 10 to 1000.

Features

  • Adjustable size — 10–100 bars on the single view, 10–35 on the comparison view (nine panels share the area).
  • Adjustable speed — 5–100 ms per step.
  • Frame-accurate playback — pause, resume, restart, and scrub to any step; the single view also has Prev/Next step buttons.
  • Animated swaps — bars slide to their new positions via CSS transform transitions (timed to the chosen speed) instead of jumping; honours prefers-reduced-motion.
  • Synced pseudocode — the panel highlights the line each snapshot is executing (toggleable).
  • Operation counters — live swap and comparison tallies.
  • Keyboard shortcuts — see below.
  • Bar value labels — optional numeric labels on each bar.
  • Persisted preferences — form inputs are saved to localStorage per view (sav:* for single, sac:* for comparison).
  • Inputs are disabled mid-run to prevent conflicts.

Keyboard shortcuts

Key Single view Comparison view
Space Pause / Resume Pause All / Resume All
/ Scrub by 1 step Adjust master progress by 1%
Shift + ← / Scrub by 10 steps Adjust master progress by 10%
Esc Close the shortcuts modal Close the shortcuts modal

The info icon at the bottom of each sidebar opens a modal listing them.

Getting started

npm install
npm start          # dev server at http://localhost:3000
npm run build      # production build
CI=true npm test -- --watchAll=false   # run the test suite once

How it works

Sorting and animation are fully decoupled.

  1. Algorithms produce snapshots, not animations. Each algorithm is a pure function (bars: Bar[]) => Step[]. It runs on a copy of the input and, after every observable mutation, pushes a Step — a deep copy of the array tagged with a state (comparing / swapping / sorted) and a 1-indexed pseudocode line. Bars carry a stable id so React keys them to the same DOM node across snapshots (so swaps reconcile rather than remount) — which is what lets bars slide to their new positions with CSS transform transitions rather than teleport. Algorithms live one-per-folder under src/algorithms/ and each default-exports an AlgorithmEntry ({ sort, label, description, pseudocode }); src/algorithms/index.ts is the registry.

  2. The playback engine replays them. usePlayback (src/hooks/use-playback.ts) walks the Step[] using one self-scheduling setTimeout at a time. Because only a single tick is ever in flight, pause is a clearTimeout, resume re-schedules from the current index, and scrub cancels and jumps to step N — all cheap. Each frame is emitted through an onFrame(bars) callback the view wires to its bar state.

Input patterns follow the same registry shape (PatternEntry per file in src/patterns/, resolved via resolvePattern).

Project structure

src/
  App.tsx                  Router shell (mounts <RouterProvider/>)
  routes.tsx               Route table (createBrowserRouter)
  types.ts                 Shared types: Bar, Step, SortFunction, AlgorithmEntry, PatternEntry
  utils.ts                 Shared helpers (clamp)
  views/
    single-algorithm-visualizer/   Single-algorithm screen (owns its form/playback state)
    algorithms-comparison/         Side-by-side comparison screen
  algorithms/
    index.ts               Registry (key → AlgorithmEntry) + resolveAlgorithm()
    algorithm-utils.ts     Snapshot helpers (snapshot, snapshotRange, finalSortedSnapshot)
    sort-contract.ts       Shared correctness test suite
    <algo>/                One folder per algorithm: <algo>.ts (entry) + <algo>.test.ts
  patterns/
    index.ts               Registry (key → PatternEntry) + resolvePattern()
    <pattern>.ts           One file per input pattern
    patterns-util.ts       randomValue / randomChoice
  components/
    view-layout/           Shared 15/85 shell (dark sidebar + visualization area)
    *-sidebar/             Per-view sidebar contents (fully controlled)
    bars-row/              Bar chart (pure)
    mini-bars-box/         Captioned mini chart for a comparison panel
    algorithm-panel/       One comparison panel (own usePlayback + imperative handle)
    pseudocode-panel/      Pseudocode display synced to the current step
    keyboard-shortcuts-modal/
    number-of-bars-control/, delay-control/, input-pattern-control/, sidebar-divider/
  hooks/
    use-playback.ts        Tick-based playback engine
    use-bars-generator.ts  bars / maxBarValue state + bar generation
    use-local-storage.ts   Persisted state
    use-keyboard-shortcuts.ts  Global key bindings

Testing

Each algorithm has a colocated *.test.ts that runs runSortCorrectnessSuite from src/algorithms/sort-contract.ts, exercising it against all five input patterns at sizes 10/25/100. Per case it checks that every snapshot is a length-preserving id-permutation of the input, the final snapshot matches the sorted multiset and is fully tagged sorted, and the input array is never mutated.

Tech stack

  • React 19 + TypeScript
  • React Router 7 (data-router mode)
  • Bootstrap 5 + react-icons
  • Create React App (react-scripts)

About

A web app that visualizes how sorting algorithms work, in real time. Step through a single algorithm with synced pseudocode and pause/scrub controls, or race all nine on the same data side-by-side, with bars that slide as they swap.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages