Visualizer CodeViz · Algorithms, visualized

Part I · Elementary sorts · week 2

Insertion sort

Slide each key left until it lands. Its cost is exactly the number of inversions in the input, so almost-sorted data is almost free.

Run the animation, step by step → generated live from any input you type — nothing is pre-recorded

Cost and properties

compares~n²/4 average
best casen−1 — already sorted
exchanges= number of inversions
stableyes

Reference: Sedgewick & Wayne, §2.1.

Insertion sort in Python

Runnable as-is, and written for reading. Watch the highlighted line move through it in the animation, or send it straight to the visualizer — it arrives with a test case ready to run, yours to edit.

Open in Visualizer

def insertion_sort(a):
    # INVARIANT: a[0..i-1] is sorted (but not necessarily final -- a later
    # key can still slide into the middle of it).
    for i in range(1, len(a)):
        j = i
        while j > 0 and a[j] < a[j - 1]:  # swap left while out of order
            a[j], a[j - 1] = a[j - 1], a[j]
            j -= 1
    return a

Why it works

The invariant, and how it differs from selection sort

a[0..i-1] is sorted — but not final. Selection sort places a key forever; insertion sort keeps a sorted prefix that later keys can still be inserted into. That is why it can exploit existing order and selection sort cannot.

Cost = inversions

Each exchange fixes exactly one inversion (a pair out of order), so the number of exchanges is precisely the number of inversions in the input, and compares are exchanges + at most n−1. Consequently insertion sort runs in linear time on partially sorted input — an array with a constant number of inversions per element sorts in O(n).

That is not a curiosity: it is why real sorting libraries switch to insertion sort for small or nearly-ordered subarrays, and why shellsort's h-sorted passes are cheap.

Stability

The loop stops on a[j] < a[j-1], strictly less. Equal keys never swap, so their original order survives — insertion sort is stable. Change that to <= and you break stability and waste time.

Watch for

The j > 0 test must come first: Python's and short-circuits, so a[j-1] is never evaluated with j == 0. Reverse the two conditions and the code reads a[-1], silently comparing against the last element of the array.

What to try in the animation

Compare already sorted (n−1 compares, zero exchanges) with reverse sorted (the full ~n²/2). No other elementary sort spreads that widely.

The animation is generated from the input box, in your browser — press Animate after editing it. To execute the Python itself, use Open in Visualizer above.

Open Insertion sort in the player →

The rest of Elementary sorts