Sorting Algorithm Visualizer

Watch bubble, insertion, selection, merge and quicksort run step by step with live comparison counts. Adjust array size, data shape and speed.

Sorting Visualizer

Live controls

90
6
205

Knobs patch the running animation live. A few (marked in the code as baked-in values like particle counts) restart the preview.

Five sorts as generators, stepped a fixed number of operations per frame.

Your code runs in a sandboxed frame with no access to this page, and it is never sent to a server. three.js demos load the library from jsDelivr; the rest need nothing but the browser.

Pick an animation

All 40 animations →

Canvas 2D
three.js
WebGL
CSS / DOM
Advertisement

Interactive Sorting Algorithm Visualizer

This visualizer animates five classic comparison sorts — bubble sort, insertion sort, selection sort, merge sort and quicksort — one operation at a time, so you can watch the array take shape and read a live count of the comparisons each algorithm performs. Choose the algorithm, the starting data shape and the array size, drag the speed slider, and see why an n log n sort pulls away from an n² sort as the input grows. It runs entirely in your browser on an HTML canvas; nothing is uploaded.

Sorting is the canonical way to learn algorithm analysis because the same task has many solutions with wildly different costs. Big-O notation tells you how those costs scale, but a number on a page is abstract. Watching bubble sort crawl while quicksort finishes in a blink — and seeing the comparison counters diverge — turns the theory into something you can feel.

What You Can Control

  • Algorithm: bubble, insertion, selection, merge or quicksort.
  • Starting data: random, nearly sorted, reversed, or few unique values. The starting shape dramatically changes how some algorithms behave.
  • Array size: from a handful of bars up to 300, so you can watch the scaling gap widen.
  • Operations per frame: effectively the speed — how many comparisons and writes are stepped each animation frame.

Each bar's height is a value; the bars being compared or swapped are highlighted. A running counter shows how many comparisons the current run has made, which is the honest measure of work that hides behind wall-clock speed.

How to Use the Visualizer

  1. Pick an algorithm. Start with bubble sort to see the naive approach, then quicksort to see a fast one.
  2. Choose a data shape. Run insertion sort on “nearly sorted” and then on “reversed” to see best case versus worst case on the same code.
  3. Set the array size. Small sizes make the steps easy to follow; large sizes make the scaling difference obvious.
  4. Adjust the speed. Slow it down to study a single pass, or speed it up to compare overall runtime.
  5. Watch the comparison counter. Compare the final counts at the same array size across algorithms — that number, not the animation length, is what complexity analysis predicts.

Complexity of the Five Algorithms

The table below summarises the standard analysis. “Stable” means equal elements keep their original order; “in-place” means it needs only a constant amount of extra memory.

AlgorithmBestAverageWorstSpaceStableIn-place
Bubble sortO(n)O(n²)O(n²)O(1)YesYes
Insertion sortO(n)O(n²)O(n²)O(1)YesYes
Selection sortO(n²)O(n²)O(n²)O(1)NoYes
Merge sortO(n log n)O(n log n)O(n log n)O(n)YesNo
QuicksortO(n log n)O(n log n)O(n²)O(log n)NoYes

The visualizer makes several of these facts tangible. Bubble and insertion sort hit their O(n) best case on nearly-sorted data — insertion sort in particular looks almost instant on the “nearly sorted” shape because its cost is the number of inversions, not n². Selection sort never changes shape: it always does the same number of comparisons regardless of input, which is why its best case is still O(n²). Merge sort writes back in sorted blocks that visibly double in width. Quicksort is fast on random data but degrades toward O(n²) when a poor pivot meets already-sorted or reversed input — run it on “reversed” to see why the last element is a bad pivot choice.

How Each Algorithm Actually Works

Bubble sort repeatedly walks the array, swapping any two adjacent elements that are out of order, so on each pass the largest remaining value “bubbles” to the end. It is the simplest to understand and the slowest in practice, doing the most writes of anything here; its only redeeming feature is that it detects an already-sorted array in a single O(n) pass.

Insertion sort builds the sorted portion one element at a time, taking the next value and sliding it left until it sits in the right place — the same way most people sort a hand of playing cards. Its cost is the number of inversions in the input, which is why it is near-instant on nearly-sorted data and a favourite fallback for small runs.

Selection sort scans the unsorted region to find the minimum and swaps it into place, once per pass. It performs the fewest writes — exactly one swap per pass — but always does the full O(n²) comparisons regardless of input, so its running shape never changes.

Merge sort splits the array in half recursively until each piece is a single element, then merges the pieces back together in order. The merges write back in sorted blocks that visibly double in width, and because it never compares the same pair twice it guarantees O(n log n) — at the cost of O(n) extra memory for the merge buffer.

Quicksort picks a pivot, partitions the array so that smaller values sit left and larger values sit right, then recurses into each side. On random data the partitions are roughly balanced and it is the fastest sort here, but a pivot that consistently lands at an extreme — as a last-element pivot does on sorted or reversed input — makes the partitions lopsided and drags it toward O(n²).

Why Real Libraries Mix Algorithms

Production sort routines are hybrids for exactly the reasons this tool illustrates. Insertion sort is unbeatable on small or nearly-ordered runs, so real implementations fall back to it there. Quicksort is fast on average but needs pivot safeguards to avoid its worst case. Merge sort is stable and predictable but uses extra memory. Widely used library sorts — introsort in C++ and Timsort in Python and Java — combine these: they start with a fast average-case sort and switch strategies when they detect the conditions that would trigger a worst case. Seeing each algorithm's strengths and failure modes on different data shapes is the intuition behind those engineering choices.

Frequently Asked Questions

Which algorithms does it visualize?

Five comparison sorts: bubble, insertion, selection, merge and quicksort.

What do the highlighted bars mean?

Bar height is the value being sorted. Highlighted bars are the two positions currently being compared or swapped on this step.

Why does insertion sort look so fast on nearly-sorted data?

Its cost is proportional to the number of inversions, not to n². Nearly-sorted input has few inversions, so it reaches its O(n) best case.

Why does quicksort sometimes look slow?

When the pivot choice is poor for the input — for example a last-element pivot on reversed data — partitioning becomes unbalanced and quicksort degrades toward its O(n²) worst case.

What is a stable sort?

A stable sort preserves the original relative order of elements that compare equal. Bubble, insertion and merge sort are stable here; selection and quicksort are not.

Why compare the counter instead of the animation length?

Animation length depends on the speed slider. The comparison counter measures actual work, which is what Big-O complexity predicts and how algorithms should be compared.

Does it run on my machine or a server?

Entirely in your browser on an HTML canvas. Nothing is uploaded.

Related Developer Tools

For hands-on data work, the data format converter reshapes JSON, YAML and CSV, and the regex tester lets you experiment with pattern matching the same interactive, in-browser way this visualizer handles sorting.

How to read the visualization

Bar height is the value being sorted and red marks the two positions involved in the current comparison or swap. The counters below the chart track comparisons and writes separately, which matters because the two costs are not interchangeable: selection sort performs the fewest writes of anything here while doing the same number of comparisons regardless of input, and bubble sort does the most writes of all.

Set the array size to 200 and run each algorithm on the same data. The gap between the quadratic sorts and the n log n sorts stops being an abstraction once you watch the counters climb side by side.

Why the starting data changes everything

The Starting data control is the most instructive part of this tool, because algorithm performance is a property of the input as much as the algorithm.

  • Nearly sorted makes insertion sort finish almost immediately, because its real cost is the number of inversions rather than the array length squared. This is why production sorts such as Timsort detect existing runs and fall back to insertion sort for them.
  • Reversed is the worst case for a quicksort that takes the last element as its pivot: every partition is maximally unbalanced and the recursion depth grows to the length of the array.
  • Random is the case most textbooks quote, and the only one where the quoted average complexities apply directly.

Generators instead of sleeps

The obvious way to animate a sort is to put a short sleep inside the inner loop. It works once, then becomes unusable: the speed cannot be changed mid-run, restarting leaves half-finished recursive calls running, and the sort is no longer the algorithm you were trying to show.

Every sort here is written as a generator that yields once per comparison and once per write. The animation loop pulls a fixed number of steps per frame, so speed is a property of the renderer rather than the algorithm, and restarting is simply discarding the generator. Recursion still works normally through yield delegation, which is why quicksort and merge sort suspend and resume as cleanly as the flat loops do.

Frequently Asked Questions

Which sorting algorithms does it show?+

Bubble sort, insertion sort, selection sort, merge sort and quicksort. Each runs on the same bar chart so you can compare them directly on identical data.

Why does insertion sort look slow on random data but fast on nearly sorted data?+

Because its cost is the number of inversions in the input, not n squared. On nearly ordered data there is almost nothing to move. That is exactly why real library sorts fall back to insertion sort for small or nearly sorted runs.

Which algorithm does the fewest writes?+

Selection sort, at one swap per pass. It still performs the same number of comparisons no matter what the input looks like, so its shape on screen never changes. Bubble sort sits at the other extreme and writes the most.

What do the red bars mean?+

Bar height is the value. Red marks the two positions being compared or swapped in the current step.

Why run quicksort on reversed data?+

To show why the last element is a poor pivot choice. On reversed input that pivot produces maximally unbalanced partitions and quicksort degrades towards n squared.

How is the animation implemented?+

Every sort is a JavaScript generator that yields once per comparison and once per write. The render loop pulls a fixed number of steps per frame, so speed is adjustable mid-run and restarting means discarding the generator. Recursive sorts suspend and resume through yield delegation.

Can I see the code?+

Yes. The HTML, CSS and JavaScript panes are editable and the code runs exactly as shown, so you can change an algorithm and watch the result immediately.

This tool is provided for informational and educational purposes only. All processing happens in your browser — no data is sent to or stored on our servers. While we strive for accuracy, we make no warranties about the completeness or reliability of results.