Module P-8·14 min read

Bubble, selection, and insertion sort — why they're O(n²), and why understanding them still matters.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Module P-8 — Sorting I: O(n²) Sorts and Why They're Slow

What this module covers: Before the two sorts that actually get used in production (Modules P-9, P-10), it's worth building — and clearly seeing the cost of — the three sorts everyone encounters first: bubble, selection, and insertion. All three are O(n²), all three are correct, and understanding exactly why they're O(n²) is what makes merge sort and quick sort's O(n log n) feel like a real, earned improvement rather than a magic number to memorize.


Bubble Sort: Repeatedly Swap Adjacent Out-of-Order Pairs

Bubble sort repeatedly scans the array, swapping any adjacent pair that's out of order — each full pass "bubbles" the largest remaining unsorted value to its correct position at the end.

typescript

The outer loop runs n times; the inner loop, for each outer iteration, checks roughly n more adjacent pairs. That's the identical nested-loop shape flagged as O(n²) back in Module F-1 — n × n comparisons in the worst case, each one only fixing a single adjacent pair before moving on.


Selection Sort: Repeatedly Find the Minimum

Selection sort takes a different approach to the same cost: on each pass, scan the entire remaining unsorted portion to find its minimum, then swap that minimum into its correct position.

typescript

Same O(n²) shape, arrived at differently: n outer iterations, each doing an O(n) scan to find the minimum. The one practical difference from bubble sort worth naming: selection sort performs at most n swaps total (one per outer iteration), while bubble sort can perform up to O(n²) swaps — a real difference if swaps are expensive (say, swapping large objects rather than plain numbers), even though both are the same Big-O time class.


Insertion Sort: Build Up a Sorted Prefix

Insertion sort grows a sorted region from the left, inserting each new element into its correct position within that already-sorted prefix:

typescript

Worst case (input in reverse order) is still O(n²) — each new element might need to shift all the way through the entire sorted prefix. But insertion sort has a property the other two don't: on already-nearly-sorted input, it's close to O(n), because the while loop barely runs at all when each new element is already close to its correct position. This isn't just a theoretical curiosity — it's exactly why some production sort implementations switch to insertion sort for small subarrays (often somewhere under 10-20 elements) even inside an otherwise O(n log n) algorithm: below a certain size, insertion sort's low overhead and near-linear behavior on partially-ordered data beats the overhead of further recursive splitting.


Why All Three Are O(n²), and Why That's Worth Feeling, Not Just Knowing

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.