An array must be ordered on a medium where a write costs far more than a comparison — a flash or EEPROM cell rated for a limited number of erase cycles, for instance. Most sorts move an element many times before it settles into its final slot, and each of those moves is a write. Selection sort commits each element with a single write instead: pass i scans the unsorted suffix a[i..n-1], finds its minimum, and swaps that minimum into position i. Every position is written at most once, so ordering an n-element array costs at most n − 1 swaps, whatever the starting order.

The scan that finds each minimum is unconditional. It inspects every remaining element, and nothing about the data — already sorted, reversed, random — changes that count. The write budget is minimal; the comparison budget is fixed.

Core condition: unsorted array, writes dearer than comparisons → one swap places each element’s final value → at most n − 1 writes but always Θ(n²) comparisons.

One pass

The trace sorts the eight-element array [8, 3, 5, 1, 9, 2, 7, 4].

The first pass scans all eight elements, finds the minimum 1 at index 3, and swaps it with a[0]. That single write fixes index 0 permanently: no smaller value remains in the suffix, so index 0 is never revisited. The second pass repeats the scan over a[1..7], now seven elements, and places 2. Each pass performs one swap and shortens the unsorted suffix by one, so the sorted prefix on the left grows by one element per pass while the comparison work on the right falls by one — the sorted region and the scanning cost move in opposite directions.

Why each placement is final

After pass i completes, a[0..i] holds the i + 1 smallest values in sorted order, and each of them is less than or equal to every value still in a[i+1..n-1]. Pass i establishes that invariant by choosing the true minimum of the suffix: no later pass can surface a smaller value to displace it, so the placement is settled and the prefix stays sorted without ever being re-examined.

The comparison count follows from the scan alone and ignores the data. Pass i tests the running minimum against each of the n − 1 − i remaining elements; summing n−1, n−2, …, 1 gives n(n−1)/2 comparisons — the same total whether the input arrives sorted, reversed, or shuffled. There is no a[j] < a[min] shortcut that ends a pass early and no outer flag that notices an already-sorted array, so the algorithm is non-adaptive: a sorted input costs exactly what a reversed one does.

Writes run the opposite way. Each pass ends in one swap — n − 1 across the whole sort in the classic formulation, and never more. That split, quadratic comparisons against linear writes, is the property that separates selection sort from every other elementary sort.

Complexity

CaseTimeSwapsAuxiliary spaceCause
BestΘ(n²)0O(1)Sorted input still triggers all n(n−1)/2 comparisons; the minimum already sits at a[i], so the guarded swap is skipped every pass.
AverageΘ(n²)O(n)O(1)The suffix scan is fixed at n(n−1)/2 comparisons; roughly n out-of-place minima each move once.
WorstΘ(n²)n − 1O(1)Every pass finds its minimum away from a[i] and performs its one swap; the comparison count is unchanged from the best case.

Comparisons dominate the running time and are identical across all three rows — the direct consequence of an unconditional scan. Swaps are the axis that varies, yet even the worst case stays linear at one swap per pass. Auxiliary space is O(1): the sort runs in place over the original array using a handful of index variables.

Boundaries

Selection sort is not stable, and the instability comes straight from the long-distance swap. Sorting [5a, 3, 5b, 1] by value: pass 0 finds the minimum 1 at index 3 and swaps it into a[0], giving [1, 3, 5b, 5a]. That swap carried 5a to the far end, behind 5b, even though 5a started ahead of it. Two keys that compared equal have had their original order reversed, and no later pass touches either again. This matters when selection sort runs as a secondary key sort: it silently scrambles the ordering the primary sort established.

A stable variant exists but abandons the write budget that motivates the algorithm. Rather than swapping the minimum into place, it removes the minimum and shifts the intervening elements up by one — the same move Insertion Sort makes. Preserving equal-key order costs Θ(n) writes per pass, restoring the Θ(n²) write total that the swap-based form was chosen to avoid.

Reference drawer

Questions

References