Basic sorting
Insertion sort and selection sort put a list in order with nothing but comparisons and moves. They cost O(n²), yet insertion sort still runs inside the fastest library sorts, and seeing why is the best way into sorting.
Sorting turns a pile into something you can search and scan
A sorted list answers questions an unsorted one can't answer quickly: binary search finds any value in O(log n), duplicates sit next to each other, and the smallest and largest items are at the ends. That is why sorting is one of the most common first steps in an algorithm.
The sorts on this page work only by comparing two items and moving items around, so they sort anything that can be compared: numbers, words, dates. Both build the sorted list one item at a time, from the left, and both keep the same promise: after step i, the first part of the list is in order.
Insertion sort slides each new item back to where it belongs
Picture sorting a hand of cards as you pick them up. Each new card is slid left past the cards larger than it and dropped into the gap. Insertion sort does exactly that: take the next item, shift every larger item in the sorted part one cell right, and drop it in.
Each shift fixes one inversion: a pair of items in the wrong order. A list has at most n(n − 1) ÷ 2 of them (when it is reversed), so the worst case is O(n²). But a list that is already sorted has none: every item is compared once and stays put, which is O(n). Nearly sorted lists cost close to that.
The rule
Insertion sort does one shift per inversion, so it costs O(n²) on a shuffled list and close to O(n) on a nearly sorted one.
Selection sort finds the smallest item and swaps it into place
Selection sort works the other way round. It scans the unsorted part for its smallest item and swaps it to the front of that part. Then the front cell is final, and the next scan starts one cell later.
Every scan looks at the whole unsorted part, so selection sort always does n(n − 1) ÷ 2 comparisons, even on a list that is already sorted. What it saves is writes: at most n − 1 swaps, one per position. That only matters when writing is much more expensive than comparing.
Bubble sort is the one to recognize, not to use
Bubble sort walks the list again and again, swapping any neighboring pair that is in the wrong order, until a full pass swaps nothing. Large items "bubble" to the end one pass at a time.
It is also O(n²), and like insertion sort it fixes one inversion per swap, but each fix costs a full three-step swap where insertion sort does a single shift. You'll meet it in textbooks and interviews; in real code, insertion sort does the same job faster.
A stable sort keeps equal items in the order they arrived
Sort a shop's orders by customer. Two orders from the same customer compare as equal, so which comes first? A stable sort promises they keep their original order. That lets you sort in passes: sort by date first, then stably by customer, and each customer's orders stay in date order.
Insertion sort is stable: it only shifts items that are strictly larger, so an item never passes an equal one. Selection sort is not. In [2a, 2b, 1], its first swap sends 2a to the back to make room for 1, giving [1, 2b, 2a]: the two 2s have changed places.
Language | Default sort | Stable? |
|---|---|---|
Python |
| Yes, guaranteed |
JavaScript |
| Yes, since ES2019 |
Java |
| Yes |
C++ |
| No; use |
Three values sort in one pass
When only three values can appear, there is no need to compare everything with everything. Keep three regions, 0s at the front, 2s at the back, 1s between, and one pass of swaps puts each item in its region. It isn't stable, but for plain values that doesn't matter.
Library sorts are faster, but insertion sort lives inside them
Sort | Comparisons | Moves | Stable | Nearly sorted input |
|---|---|---|---|---|
Insertion | O(n²) | O(n²) shifts | Yes | Close to O(n) |
Selection | Always n(n − 1) ÷ 2 | At most n − 1 swaps | No | No faster |
Bubble | O(n²) | O(n²) swaps | Yes | O(n) with an early stop |
For anything large, the O(n log n) sorts on the next pages win by a wide margin. But on a few dozen items, insertion sort's tiny constant beats them, so fast library sorts switch to insertion sort for small pieces. Python's sort, Timsort, also takes advantage of runs that are already in order, which is insertion sort's strength.
4 questions
Remember this
- Insertion sort slides each item left past larger ones: O(n²) in general, close to O(n) on nearly sorted input.
- Selection sort swaps the smallest remaining item into place: always n(n − 1) ÷ 2 comparisons, at most n − 1 swaps.
- Bubble sort is O(n²) with more work per fix than insertion sort; recognize it, don't use it.
- A stable sort keeps equal items in their original order, which lets you sort by several keys in passes.
- Library sorts are O(n log n) but switch to insertion sort for small pieces.
Now solve some yourself
Only this topic 0 of 8 solved
- EasyHow many people stand out of order?
- EasyTwo horses with the closest skill
- EasyCubes fall to the right when gravity turns
- EasyRebuild the arrival order from counts
- EasyEven numbers before odd
- EasyThe value that fills more than half
- EasyPairs with the smallest gap
- MediumArrange numbers into the largest number
Mixed with topics you have practiced 0 unlocked
2 more once you have practiced Linear-time sorting, Linked lists. Play one of its examples to the end and solve one of its problems to unlock them.
Problems open on their own sites (LeetCode, Codeforces, CodeChef, AtCoder, CSES) in a new tab. Tick Solved when you get it accepted there; your ticks decide which mixed problems open next.
Next