Selection Sort

Sorting
In-place
avg O(n²)

Selection sort has the simplest plan of all sorting algorithms: find the smallest value, put it first. Find the next smallest, put it second. Repeat until nothing is left. It does the same amount of work no matter what the input looks like - but it makes very few swaps, and that is its one real strength.

Watch it sort

Press play - or drag the timeline and step through it yourself.
Pass 1Comparisons 0Swaps 0Step 1 / 202

18 values. Each pass finds the smallest value that is left and puts it at the front.

comparing swapping final position untouched

Complexity

Best
O(n²)
Input already in order
Average
O(n²)
Normal mixed input
Worst
O(n²)
Worst possible input
Space
O(1)
Extra memory used
Stable: no - equal values keep their orderIn-place: yes - no copy of the array needed

Picking the shortest player first

A coach lines up players by height. The coach walks the whole line, finds the shortest player, and sends them to the front. Then walks the rest of the line, finds the next shortest, and puts them second. Each walk picks ("selects") exactly one player, and that player never moves again. After enough walks, the line is sorted. Notice: lots of looking, very little moving.

How it works, step by step

  1. Look through the whole array and remember where the smallest value is.

  2. Swap that smallest value with the value in the first position. The first slot is now final.

  3. Look through the rest of the array (from position 2 onward) for the next smallest.

  4. Swap it into the second position. That slot is final too.

  5. Repeat. Each pass shrinks the unsorted part by one.

  6. After n−1 passes, only one value is left - and it must be the biggest, so it is already in place.

The code, in JavaScript

The whole algorithm: an outer loop for the position to fill, an inner loop to find the smallest value for it.

javascript
function selectionSort(arr) {
  const a = [...arr];              // copy, so we don't change the input
  const n = a.length;

  for (let i = 0; i < n - 1; i++) {
    let min = i;                   // assume the first unsorted value is smallest

    // Scan the rest - did we assume wrong?
    for (let j = i + 1; j < n; j++) {
      if (a[j] < a[min]) min = j;
    }

    // Put the true smallest at position i.
    if (min !== i) {
      [a[i], a[min]] = [a[min], a[i]];
    }
  }

  return a;
}

selectionSort([5, 1, 4, 2]);       // → [1, 2, 4, 5]

Dry run: sorting [5, 1, 4, 2]

The same steps the visualizer plays, written as a table. Generated by running the real algorithm - not written by hand.

StepPassArrayWhat happened
11[5, 1, 4, 2]Pass 1: start at position 1. Current smallest: 5.
21[5, 1, 4, 2]1 < 5 - new smallest found.
31[5, 1, 4, 2]4 ≥ 1 - keep 1 as the smallest.
41[5, 1, 4, 2]2 ≥ 1 - keep 1 as the smallest.
51[1, 5, 4, 2]Scan done. Swap 1 into position 1.
62[1, 5, 4, 2]Pass 2: start at position 2. Current smallest: 5.
72[1, 5, 4, 2]4 < 5 - new smallest found.
82[1, 5, 4, 2]2 < 4 - new smallest found.
92[1, 2, 4, 5]Scan done. Swap 2 into position 2.
103[1, 2, 4, 5]Pass 3: start at position 3. Current smallest: 4.
113[1, 2, 4, 5]5 ≥ 4 - keep 4 as the smallest.

Good choice when…

  • Writing to memory is expensive and you want the minimum number of swaps - selection sort does at most n−1, the fewest of any comparison sort.
  • The array is tiny and you want code you can write from memory without thinking.
  • You are teaching the idea of an invariant: after pass k, the first k slots are final and never touched again.

Bad choice when…

  • The input is already almost sorted. Selection sort cannot take advantage - it always scans everything, so it is O(n²) even on sorted data. Insertion sort or bubble sort with early exit beat it there.
  • You need a stable sort. The long-distance swap can jump one value over an equal one, changing their original order.
  • The array has any real size - the O(n²) comparisons dominate everything.

Common mistakes

  • People expect the `swapped`-flag trick from bubble sort to work here. It does not: selection sort makes at most one swap per pass anyway, and the scan itself is the cost.
  • Selection sort is not stable. Sorting [5a, 5b, 1] swaps 1 with 5a, giving [1, 5b, 5a] - the two fives changed order. If that matters, use insertion or merge sort.
  • Do not swap inside the inner loop. The whole point is to scan first, swap once. Swapping every time you find a smaller value turns it into a worse bubble sort.
  • The best case is O(n²) too. Bubble sort with early exit is O(n) on sorted input; selection sort never is. "Simplest" is not the same as "fastest".

Selection Sort vs. its closest relatives

AlgorithmBestAverageWorstSpaceStable
Selection Sortthis pageO(n²)O(n²)O(n²)O(1)no
Bubble SortO(n)O(n²)O(n²)O(1)yes
Insertion SortO(n)O(n²)O(n²)O(1)yes
Heap SortO(n log n)O(n log n)O(n log n)O(1)no
Quick SortO(n log n)O(n log n)O(n²)O(log n)no