← SciSim / Computer Science

Selection Sort

⚙️ Tier: HSC / Early Undergraduate
📊 Section 1 — Interactive Simulation
Step 0 / 0
Press Play or use step controls to run Selection Sort.
0
Comparisons
0
Swaps
0
Step
20
Input n
0
Pass #
Scanning
Current Minimum
Swapping
Sorted
Unprocessed
Pseudocode
1procedure SelectionSort(A[0..n-1]): 2 for i ← 0 to n-2 do 3 minIdx ← i // assume current position is minimum 4 for j ← i+1 to n-1 do 5 if A[j] < A[minIdx] then 6 minIdx ← j 7 if minIdx ≠ i then 8 swap(A[i], A[minIdx]) 9 return A
Input Size (n)
n = 20
Preset
Custom Input
Actions
Display Options
Index Labels
Value Labels
Min Pointer
Swap Animation
💡 Section 2 — The Idea, Step by Step

Start simple: line up the class

Imagine lining up a class from shortest to tallest. The most natural method needs no cleverness at all: look across everyone, spot the single shortest person, and walk them to the front. Now pretend that person has vanished, look again at who is left, find the new shortest, and place them second. Keep going until nobody is left to move. That is exactly what Selection Sort does with numbers — each round it selects the smallest value still out of place and drops it straight into its final spot.

Put numbers on it

Call the list size $n$. The work splits into rounds called passes. In the first pass you compare your current best-guess minimum against every other element, just to be certain you really found the smallest — that costs $n-1$ comparisons. The next pass has one fewer element left to check, so $n-2$ comparisons, then $n-3$, and so on down to $1$. For a tiny list of $n=5$ that is $4+3+2+1=10$ comparisons. The pattern to notice: each pass costs about $n$ checks and there are about $n$ passes, so the effort grows like $n \times n$.

The precise picture

Adding the passes exactly gives the total comparison count:

$$T(n)=\sum_{i=0}^{n-2}(n-1-i)=\frac{n(n-1)}{2}=\Theta(n^2).$$

The striking part is that this total never changes. A list that is already sorted costs exactly the same as a shuffled one, because the inner scan has no way to know it has found the minimum without checking every remaining element — Selection Sort is input-oblivious. Its one redeeming trick is movement: it swaps data only once per pass, at most $n-1$ times in total, which is why it shines on write-expensive memory like flash. In the sim, the n slider sets the list size, the Preset menu picks the starting order, and the red cell marks the current minimum while the blue scanner sweeps to the right.

Try this in the sim above: (1) set the preset to Already sorted and watch the comparison counter still climb all the way to $\frac{n(n-1)}{2}$ — there is no shortcut. (2) Switch to Reverse sorted and confirm the comparison count is identical, then watch the much smaller swap counter. (3) Shrink n and step through one full pass to see the red minimum-marker jump only at the moment a smaller value appears.

Key takeaway: Selection Sort always makes $\frac{n(n-1)}{2}$ comparisons but at most $n-1$ swaps — cheap on writes, but never any faster on a list that happens to be sorted.
📐 Section 3 — Algorithm Analysis & Derivation

Selection Sort — Origin & History

Selection Sort is one of the most intuitive sorting algorithms, introduced in early computer science literature. It works by repeatedly finding the minimum element from the unsorted portion and placing it at the beginning. Despite being conceptually simple, its key property is that it performs at most n−1 swaps — exactly one per pass — making it optimal for write-expensive memory (flash storage, magnetic media).

Symbol Table

SymbolMeaningRange
\(n\)Input array size\(\mathbb{Z}^+\)
\(T(n)\)Number of comparisons\(\frac{n(n-1)}{2}\) (all cases)
\(S(n)\)Number of swaps\([0, n-1]\)
\(i\)Outer loop — current sorted boundary\(0 \leq i \leq n-2\)
\(j\)Inner loop — scan position\(i+1 \leq j \leq n-1\)
minIdxIndex of current minimum found\(i \leq \text{minIdx} \leq n-1\)

Step-by-Step Complexity Derivation

Step 1 — Inner loop iterations per pass

In pass \(i\), the inner loop scans positions \(i+1\) through \(n-1\), performing \(n-1-i\) comparisons to find the minimum:

$$\text{Comparisons in pass } i = n - 1 - i$$

Step 2 — Total comparison count (all cases)

Unlike Bubble Sort, Selection Sort makes the same number of comparisons regardless of input order — there is no early exit:

$$T(n) = \sum_{i=0}^{n-2}(n-1-i) = \sum_{k=1}^{n-1} k = \frac{n(n-1)}{2}$$

Step 3 — Asymptotic class

$$\boxed{T(n) = \Theta(n^2)} \text{ — best, worst, and average are all identical}$$

Step 4 — Swap count: Selection Sort's key advantage

Each pass performs at most 1 swap (when minIdx ≠ i). So the total number of swaps is at most \(n-1\):

$$S(n) \leq n - 1 = \mathcal{O}(n)$$

Compare this to Bubble Sort's worst-case \(\frac{n(n-1)}{2}\) swaps. For write-costly storage, Selection Sort is dramatically better.

Step 5 — Space complexity

$$\text{Space} = \mathcal{O}(1) \text{ auxiliary — in-place algorithm}$$

Step 6 — Stability

Standard Selection Sort is NOT stable. When the minimum is found and swapped to position \(i\), it can jump over equal elements, disturbing their relative order. Example: swapping A[0]=3 with A[3]=1 in [3a, 3b, 2, 1] places 1 at front but moves 3a past 3b.

Step 7 — No input-sensitive optimization possible

Selection Sort cannot be improved by early exit because its inner loop must scan the entire unsorted region to guarantee finding the minimum. \(T(n) = \Theta(n^2)\) in all cases — there is no best case improvement unlike Bubble Sort or Insertion Sort.

Worked Trace Example (n = 5)

Array: [64, 25, 12, 22, 11]

Pass 0 (i=0): Scan [1..4], find min=11 at index 4. Swap A[0]↔A[4] → [11, 25, 12, 22, 64]. Swaps: 1.

Pass 1 (i=1): Scan [2..4], find min=12 at index 2. Swap A[1]↔A[2] → [11, 12, 25, 22, 64]. Swaps: 1.

Pass 2 (i=2): Scan [3..4], find min=22 at index 3. Swap A[2]↔A[3] → [11, 12, 22, 25, 64]. Swaps: 1.

Pass 3 (i=3): Scan [4..4], min=25 at index 3 (no swap needed). Comparisons: 1, Swaps: 0.

Final: [11, 12, 22, 25, 64]. Total comparisons: 10 = \(\frac{5×4}{2}\). Total swaps: 3.

References

[1] Cormen et al. — CLRS 4th ed. 2022, Ch. 2 (Exercise 2.2-2)
[2] Sedgewick & Wayne — Algorithms 4th ed., §2.1 "Elementary Sorts"
[3] Knuth — TAOCP Vol. 3, §5.2.3 "Sorting by Selection"
❓ Section 4 — FAQ
⚙️ ConceptualWhy does Selection Sort always make exactly \(\frac{n(n-1)}{2}\) comparisons?
Selection Sort must scan the entire unsorted portion to identify the minimum. It has no mechanism to skip comparisons — even if the array is sorted, it still scans every element to confirm the minimum. This makes Selection Sort input-oblivious: its comparison count is a fixed function of \(n\), unlike Bubble Sort (with early exit) or Insertion Sort. The invariant is: after pass \(i\), exactly the \(i\) smallest elements are in their final positions.
Key takeaway: \(T(n) = \Theta(n^2)\) for all inputs — no best case improvement exists without fundamentally changing the algorithm.
🌍 AppliedWhere is Selection Sort's O(n) swap property practically useful?
Flash storage (SSDs, EEPROMs) has write endurance limits — each cell can only be written a finite number of times. In embedded systems where data is stored in flash and needs infrequent sorting, Selection Sort's at-most \(n-1\) writes is a significant advantage. It's also used in systems where data movement is physically expensive — e.g., sorting records on tape drives where seeks cost time. Modern systems rarely need this, but it matters in constrained IoT and embedded environments.
Key takeaway: For write-expensive media, Selection Sort's O(n) swaps beats Bubble Sort's O(n²) swaps even though comparisons are the same.
🔬 SimulationWhat is the simulation showing, and how do I read the red marker?
The red cell marks the current minimum found so far in the ongoing scan. Blue cells are the elements currently being compared against the red minimum. As the scan progresses, the red marker moves whenever a smaller element is found. At the end of each pass, the red minimum is swapped (shown in orange) with the element at position \(i\). Green cells are already in their final sorted positions. The pointer below the array shows the current scan position \(j\) and the current minimum position minIdx.
Key takeaway: The red cell chases the minimum across the unsorted region — watch how it "updates" each time a new smaller element is found.
💡 Non-ObviousWhy is Selection Sort NOT stable, and can it be made stable?
Standard Selection Sort swaps the minimum directly to position \(i\), which can skip over equal elements and disturb their order. Example: sorting [(3,a), (3,b), (1,c)] by value: pass 0 finds minimum at index 2, swaps with index 0 → [(1,c), (3,b), (3,a)]. Now (3,a) and (3,b) are out of their original order. Selection Sort can be made stable by using insertion instead of swapping — shift elements rightward to create a slot for the minimum, rather than directly swapping. This maintains O(n²) comparisons but now uses O(n) shifts per pass instead of O(1) swaps.
Key takeaway: Stable Selection Sort trades the O(n) swap advantage for stability — you can't have both with a simple modification.
📐 ComplexitySelection Sort has the same O(n²) as Bubble Sort — why is it considered "better"?
The asymptotic complexity is the same, but the constant factors differ significantly in swap count. Bubble Sort: up to \(\frac{n(n-1)}{2}\) swaps. Selection Sort: at most \(n-1\) swaps. Since a swap typically involves 3 assignments (using a temp variable), the real operation count for swaps differs by a factor of \(\frac{n}{2}\). In practice, comparisons are cheap (register operations) while swaps involve data movement (memory writes). Selection Sort also has simpler inner loop logic, giving better cache behavior for small arrays.
Key takeaway: Same Big-O doesn't mean same performance — constant factors, cache behavior, and swap count matter enormously in practice.
🎓 DeepWhat is the connection between Selection Sort and the concept of a "tournament"?
Each pass of Selection Sort is logically equivalent to running a tournament to find the champion (minimum). Heap Sort is a direct algorithmic improvement on this idea: instead of rescanning from scratch each pass (O(n) per pass), it maintains a heap data structure that allows finding the next minimum in O(log n). This reduces total complexity from O(n²) to O(n log n). The insight — reuse comparison work across passes via a priority structure — is the key algorithmic advance from Selection Sort to Heap Sort, illustrating how data structures enable algorithm speedups.
Key takeaway: Heap Sort = Selection Sort + a heap; the heap makes the "find minimum" step O(log n) instead of O(n), giving the asymptotic improvement.

References

CLRS — Introduction to Algorithms (4th ed.) · Visualgo — visualgo.net/en/sorting · MIT 6.006 OCW
⚠️ Section 5 — Misconceptions & Common Errors

Sub-block A: Conceptual Misconceptions

❌ Misconception: "Selection Sort has a best case of O(n) like Bubble Sort."
✅ Correction: Selection Sort has no early-exit mechanism. Its comparison count is identically \(\frac{n(n-1)}{2}\) for every input — sorted, reverse-sorted, or random. This is because the inner loop must scan all remaining elements to guarantee it has found the true minimum. There is no optimization analogous to Bubble Sort's swapped flag for Selection Sort.
📖 CLRS 4th ed., Exercise 2.2-2
❌ Misconception: "Selection Sort is stable because equal elements maintain relative order."
✅ Correction: Standard Selection Sort is NOT stable. The direct swap can move an element past equal elements. For example, sorting [(3a), (3b), (1)] finds min=1 at index 2 and swaps with index 0, giving [(1), (3b), (3a)] — the two 3s are now reversed. Stability requires either using insertion-style shifting (O(n) writes per pass) or a modified algorithm that finds the last occurrence of the minimum.
📖 Knuth TAOCP Vol. 3, §5.2.3
❌ Misconception: "Selection Sort makes O(n²) swaps like Bubble Sort."
✅ Correction: Selection Sort makes at most \(n-1\) swaps — exactly one per pass (and zero if the minimum is already in place). This is a crucial distinction: Bubble Sort can make up to \(\frac{n(n-1)}{2}\) swaps. For write-expensive storage or systems where data movement is costly, Selection Sort is drastically better despite identical comparison counts.
📖 Sedgewick & Wayne — Algorithms 4th ed., §2.1

Sub-block B: Implementation Errors

❌ Error: Starting inner loop at j = i instead of j = i+1.
✅ Correct: The inner loop should start at j = i+1. Starting at j = i compares the element at position i with itself, never updating minIdx incorrectly but wasting one comparison per pass. More importantly, it signals a misunderstanding of the invariant: position i starts as the assumed minimum, not a candidate to beat itself.
🔍 Students treat the current position as a candidate rather than the initial minimum assumption.
❌ Error: Swapping unconditionally: swap(A[i], A[minIdx]) without checking if minIdx != i.
✅ Correct: Always check if minIdx != i before swapping. An unconditional swap when minIdx == i results in a self-swap (A[i]↔A[i]), which is harmless but wastes a write operation. In write-expensive environments, this doubles the worst-case write count needlessly. The check also makes the algorithm's swap count correctly bounded by \(n-1\).
🔍 Students overlook the no-op swap case, inflating the actual write count.
❌ Error: Claiming Selection Sort's outer loop should run to n-1: for i in range(n).
✅ Correct: The outer loop runs to n-2 (i.e., range(n-1)). After \(n-1\) passes, the last remaining element is automatically in its correct position — no comparison or swap needed. Running to \(n-1\) causes an inner loop with zero iterations on the last pass — harmless but unnecessary.
🔍 Students apply the same bound as array length without reasoning about the invariant.

References

CLRS 4th ed. · Sedgewick & Wayne — Algorithms 4th ed. · Skiena — Algorithm Design Manual 3rd ed.