Selection Sort

Intro

Selection sort builds a sorted prefix by repeatedly finding the minimum element in the unsorted suffix and swapping it into place. It always performs exactly O(n²) comparisons regardless of input order, but only O(n) swaps — making it useful in the rare case where writes are expensive but comparisons are cheap.

Mechanism

For each position i, scan a[i..n-1] to find the minimum, then swap it with a[i]. After each iteration, the sorted prefix grows by one element.

graph TD
  A[Start array A] --> B[Set i to 0]
  B --> C{i less than n minus 1}
  C -->|No| Z[Done]
  C -->|Yes| D[Set min to i and set j to i plus 1]
  D --> E{j less than n}
  E -->|No| F[Swap A at i and A at min]
  F --> G[Increment i]
  G --> C
  E -->|Yes| H{A at j less than A at min}
  H -->|Yes| I[Set min to j]
  H -->|No| J[No op]
  I --> K[Increment j]
  J --> K
  K --> E

Complexity

Case Time Space Swaps
Best O(n²) O(1) O(n)
Average O(n²) O(1) O(n)
Worst O(n²) O(1) O(n)

Properties: in-place, typically not stable (a swap can reorder equal keys), exactly n−1 swaps in the worst case.

C# Implementation

public static void SelectionSort(int[] a)
{
    int n = a.Length;
    for (int i = 0; i < n - 1; i++)
    {
        int minIdx = i;
        for (int j = i + 1; j < n; j++)
        {
            if (a[j] < a[minIdx])
                minIdx = j;
        }
        if (minIdx != i)
            (a[i], a[minIdx]) = (a[minIdx], a[i]);
    }
}

When to Use

Rarely in production. The O(n) swap count is its only advantage over bubble sort. Consider it when:

For general use, prefer insertion sort (better on nearly-sorted data) or Array.Sort (introsort).

Pitfalls

Using Selection Sort When Stability Is Required

What goes wrong: selection sort swaps the minimum element into position, which can move an equal element past another equal element, breaking stability. A developer uses it for a secondary sort (e.g., sort by name after sorting by age) and the primary sort order is corrupted.

Mitigation: use insertion sort or merge sort when stability is required. Selection sort is only appropriate when writes are significantly more expensive than reads (e.g., flash memory) and stability is not needed.

Choosing Selection Sort Over Insertion Sort for Small Arrays

What goes wrong: selection sort is chosen for small arrays because it has O(n) swaps. But for small n, the swap count advantage is negligible, and insertion sort is faster in practice due to better cache behavior and O(n) best case on nearly-sorted data.

Mitigation: prefer insertion sort for small arrays. Use selection sort only when writes are measurably more expensive than reads in your specific hardware context.

Tradeoffs

Algorithm Time (avg) Stable Swaps Best case Use when
Selection sort O(n²) No O(n) O(n²) Writes are expensive (flash memory); stability not needed
Insertion sort O(n²) Yes O(n²) shifts O(n) Small arrays; nearly-sorted data; stability needed
Merge sort O(n log n) Yes O(n log n) O(n log n) Stability required; large arrays; linked lists
Array.Sort (introsort) O(n log n) No O(n log n) O(n log n) General-purpose in-memory sorting

Decision rule: selection sort's only advantage is O(n) swaps. Use it only when writes are significantly more expensive than reads (flash memory, EEPROM). For all other cases, use insertion sort (small arrays) or Array.Sort (large arrays).

Questions

References


Whats next