An in-place comparison sorting algorithm. It divides the input list into two parts: a sorted sublist which is built up from left to right and a sublist of the remaining unsorted items that occupy the rest of the list. Initially, the sorted sublist is empty and the unsorted sublist is the entire input list. The algorithm proceeds by finding the smallest (or largest, depending on sorting order) element in the unsorted sublist, exchanging (swapping) it with the leftmost unsorted element (putting it in sorted order), and moving the sublist boundaries one element to the right.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
{
"arr": "[64, 25, 12, 22, 11]",
"n": 5
}Overview
Selection Sort splits the array into a sorted prefix and an unsorted suffix. On every pass it scans the whole unsorted suffix to find the smallest value, then swaps that value into the first unsorted slot. The sorted prefix grows by exactly one element per pass.
The key property is that it performs at most n - 1 swaps in total, no matter what the input looks like. The number of comparisons, however, is always about n^2/2, because finding a minimum requires looking at every remaining element.
With the default input 64, 25, 12, 22, 11, the first pass finds 11 and swaps it with 64; the second finds 12 and swaps it with 25. Watch min_idx in the variable inspector change as smaller values are discovered.
Step by step
- Set
i = 0as the boundary between the sorted and unsorted parts. - Assume
arr[i]is the minimum and remember its index inmin_idx. - Scan
jfromi + 1to the end; wheneverarr[j] < arr[min_idx], updatemin_idx. - Swap
arr[i]witharr[min_idx]. - Increase
iand repeat until only one unsorted element is left.
Complexity
| Case | Cost | Why |
|---|---|---|
| Best case | O(n^2) | Even sorted input needs a full scan to confirm each minimum. |
| Average case | O(n^2) | n(n-1)/2 comparisons regardless of order. |
| Worst case | O(n^2) | Same comparison count; swaps never exceed n - 1. |
| Extra space | O(1) | Only min_idx and a temporary for the swap. |
When to use it
- When writes are expensive compared with reads, for example flash memory or EEPROM, because it does the fewest swaps of the simple sorts.
- Small arrays where predictable, input-independent running time is useful.
- As a stepping stone to Heap Sort, which is selection sort with a faster way of finding the minimum.
Common mistakes
- It is not stable: the long-distance swap can jump an element over an equal one. Sorting
[2a, 2b, 1]moves2abehind2b. - Swapping inside the inner loop, every time a smaller value is seen, turns it into a slower, more confusing variant of Bubble Sort.
- It never finishes early, so it is a poor choice when the input is often already sorted.
A dry run is the best way to check your understanding of Selection Sort: follow each row, predict the next one, and compare. The run below takes 47 steps in total. Steps that only re-print loop counters are left out so the decisions stand out. The Line column refers to the line numbers in the code listing above.
- Input
- 64, 25, 12, 22, 11
- Result
- arr = [11, 12, 22, 25, 64], return value = [11, 12, 22, 25, 64]
| Step | Line | Array | What happens |
|---|---|---|---|
| 1 | 2 | [64, 25, 12, 22, 11] | n = 5 |
| 5 | 6 | [64, 25, 12, 22, 11] | n = 5, i = 0, min_idx = 0, j = 1, comparison = 25 < 64 |
| 8 | 6 | [64, 25, 12, 22, 11] | n = 5, i = 0, min_idx = 1, j = 2, comparison = 12 < 25 |
| 11 | 6 | [64, 25, 12, 22, 11] | n = 5, i = 0, min_idx = 2, j = 3, comparison = 22 < 12 |
| 13 | 6 | [64, 25, 12, 22, 11] | n = 5, i = 0, min_idx = 2, j = 4, comparison = 11 < 12 |
| 16 | 11 | [64, 25, 12, 22, 64] | n = 5, i = 0, min_idx = 4, temp = 11, arr[min_idx] = 64 |
| 17 | 12 | [11, 25, 12, 22, 64] | n = 5, i = 0, min_idx = 4, temp = 11, arr[i] = 11 |
| 21 | 6 | [11, 25, 12, 22, 64] | n = 5, i = 1, min_idx = 1, j = 2, comparison = 12 < 25 |
| 24 | 6 | [11, 25, 12, 22, 64] | n = 5, i = 1, min_idx = 2, j = 3, comparison = 22 < 12 |
| 26 | 6 | [11, 25, 12, 22, 64] | n = 5, i = 1, min_idx = 2, j = 4, comparison = 64 < 12 |
| 28 | 11 | [11, 25, 25, 22, 64] | n = 5, i = 1, min_idx = 2, temp = 12, arr[min_idx] = 25 |
| 29 | 12 | [11, 12, 25, 22, 64] | n = 5, i = 1, min_idx = 2, temp = 12, arr[i] = 12 |
| 33 | 6 | [11, 12, 25, 22, 64] | n = 5, i = 2, min_idx = 2, j = 3, comparison = 22 < 25 |
| 36 | 6 | [11, 12, 25, 22, 64] | n = 5, i = 2, min_idx = 3, j = 4, comparison = 64 < 22 |
| 38 | 11 | [11, 12, 25, 25, 64] | n = 5, i = 2, min_idx = 3, temp = 22, arr[min_idx] = 25 |
| 39 | 12 | [11, 12, 22, 25, 64] | n = 5, i = 2, min_idx = 3, temp = 22, arr[i] = 22 |
| 43 | 6 | [11, 12, 22, 25, 64] | n = 5, i = 3, min_idx = 3, j = 4, comparison = 64 < 25 |
| 47 | 14 | [11, 12, 22, 25, 64] | return value = [11, 12, 22, 25, 64] |