Skip to content
K Knidox Search…
Computer Science · Algorithms

Sorting Algorithms

Watch bubble, selection, insertion, merge, quick and heap sort run on your own numbers, step by step with the counts.

Algorithm
Comma or space separated, up to 40 values.
Comparisons
27

Θ(n) best, Θ(n²) average, Θ(n²) worst

Swaps
13

each swap exchanges two elements

Extra memory
O(1)

stable — equal values keep their original order

Step by step
0
42719388256114
0c
1
74219388256114
1c
2
71942388256114
2c
3
71934288256114
3c
4
71934288256114
4c
5
71934225886114
5c
6
71934225618814
6c
7
71934225611488
7c
8
71934225611488
8c
9
73194225611488
9c
10
73194225611488
10c
11
73192542611488
11c
12
73192542611488
12c
13
73192542146188
13c
14
37192542146188
14c
15
37192542146188
15c
16
37192542146188
16c
17
37192542146188
17c
18
37192514426188
18c
19
37192514426188
19c
20
37192514426188
20c
21
37192514426188
21c
22
37191425426188
22c
23
37191425426188
23c
24
37191425426188
24c
25
37141925426188
25c
26
37141925426188
26c
27
37141925426188
27c
28
37141925426188
27c

Highlighted cells are the ones the step touched; green cells are in their final place.

Every algorithm on this same input
AlgorithmComparisonsMovesWorst caseStable
Bubble sort2713Θ(n²)yes
Selection sort285Θ(n²)no
Insertion sort1813Θ(n²)yes
Merge sort1624Θ(n log n)yes
Quicksort167Θ(n²)no
Heapsort2519Θ(n log n)no
Inputs — tap to load

Bubble, selection and insertion sort all take Θ(n²) comparisons in the worst case; merge, quick and heap sort take Θ(n log n). The counts above are the real ones for your input, so the difference between best and worst case shows up directly.

The three quadratic sorts are not interchangeable

Textbooks group bubble, selection and insertion sort together as the slow ones, which hides what separates them. Run all three on eight already-sorted values and the difference is stark: insertion and bubble sort finish in 7 comparisons and no moves at all, while selection sort still does 28 comparisons. Selection sort cannot take advantage of order, because finding the minimum of the remaining part always means looking at all of it. Its comparison count is exactly n(n−1)/2 for every input that exists.

That rigidity buys one thing. Selection sort makes at most n − 1 swaps, where bubble sort makes one swap per inversion — on eight reversed values, 28 of them. If moving an element is expensive and comparing is cheap, selection sort is the one you want, and it is the reason it survives in contexts where writes cost far more than reads.

What the move counts actually measure

Both bubble sort’s swaps and insertion sort’s shifts equal the number of inversions in the input — the count of pairs that start out in the wrong order. That is not an approximation, it is exact, and it is the cleanest way to see why nearly sorted data is cheap for them: few inversions, few moves. Merge sort ignores this entirely. It moves every element once per level of recursion whatever the input, so its move count is the same for sorted, reversed and random data, and only its comparison count varies.

selection sort: exactly n(n − 1) ÷ 2 comparisons, for every input  ·  bubble and insertion: moves = number of inversions

two exact identities, not bounds — the tool checks them on whatever you enter

  1. 1
    Write the array out once per pass, not once per swap. An exam answer wants the state after each outer-loop pass. Tracing every inner comparison fills a page and hides the structure.
  2. 2
    Mark which end is finished. Bubble sort settles the largest value at the right on each pass; selection and insertion sort build a sorted run from the left.
  3. 3
    For insertion sort, remember the held value. The element being inserted is lifted into a variable first, so mid-pass the array genuinely has a duplicate and a stale slot.
  4. 4
    For merge and quicksort, draw the recursion as a tree. The work happens on the way back up for merge sort, and on the way down for quicksort — that is the whole difference between them.
  5. 5
    Count comparisons separately from moves. They answer different questions, and an algorithm can be good at one and bad at the other.

The six algorithms compared

Space is the extra memory beyond the array itself. Stable means equal values keep their original relative order.

AlgorithmBestAverageWorstSpaceStable
Bubble sortΘ(n)Θ(n²)Θ(n²)O(1)Yes
Selection sortΘ(n²)Θ(n²)Θ(n²)O(1)No
Insertion sortΘ(n)Θ(n²)Θ(n²)O(1)Yes
Merge sortΘ(n log n)Θ(n log n)Θ(n log n)O(n)Yes
QuicksortΘ(n log n)Θ(n log n)Θ(n²)O(log n)No
HeapsortΘ(n log n)Θ(n log n)Θ(n log n)O(1)No

Why quicksort wins in practice despite the worst case

On paper heapsort looks strictly better than quicksort: the same average behaviour, a guaranteed Θ(n log n) worst case instead of a quadratic one, and constant extra space instead of a recursion stack. In practice quicksort is usually faster, because its inner loop is a single forward scan over contiguous memory while heapsort jumps between indices i, 2i+1 and 2i+2 — a pattern that defeats the cache badly at any realistic size. The comparison counts above are equal; the time is not.

The quadratic worst case is real but avoidable. Lomuto partitioning with the last element as pivot, which is what the trace here shows, degrades to Θ(n²) on already-sorted input — the counts will show it. Choosing the pivot at random, or as the median of three, makes that case vanishingly unlikely. Production sorts go further: introsort watches its own recursion depth and switches to heapsort if the partitioning is going badly, so it keeps quicksort’s speed and heapsort’s guarantee.

Stability is the property that decides the rest. If you sort a list of records by date and then by name, a stable sort leaves same-name records still in date order, and an unstable one scrambles them. Bubble, insertion and merge sort are stable because they only ever move an element past something strictly greater; selection, quick and heap sort exchange distant elements and lose the original order of ties. This is why Python and Java use merge-sort variants for objects — Timsort and its relatives — and reserve quicksort for primitives, where equal values are indistinguishable and stability means nothing.

Which sorting algorithm is fastest?
For large inputs, quicksort in practice and merge sort when stability or a guaranteed bound matters. For small or nearly sorted inputs, insertion sort beats all of them, which is why real implementations switch to it below about 16 elements.
What does stable mean?
Equal values keep the order they started in. It matters when you sort by one key after another: a stable sort preserves the earlier ordering within ties, an unstable one does not.
Why is bubble sort taught if nobody uses it?
Because its invariant is the easiest to see — after k passes the largest k values are in place — and because its swap count equals the inversion count exactly, which makes it a clean introduction to counting work.
When is quicksort Θ(n²)?
When the pivot repeatedly splits off almost nothing. With the last element as pivot, already-sorted input does exactly that. Random or median-of-three pivot choice makes it very unlikely.
Why does merge sort need extra memory?
Merging two sorted runs in place is possible but slow and intricate. The standard version copies into a buffer of size n, which is the price of its guaranteed Θ(n log n) and its stability.
Can anything sort faster than n log n?
Not by comparing elements — that needs at least ⌈log₂ n!⌉ comparisons in the worst case. Counting sort and radix sort beat it by not comparing at all, at the cost of assuming something about the keys.
Why does insertion sort show a duplicate mid-trace?
It lifts the element being inserted into a separate variable, then shifts larger values right one at a time. Until the held value drops back in, one slot genuinely holds a stale copy — the trace marks it rather than hiding it.