A simple sorting algorithm that builds the final sorted array one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. However, it provides several advantages: simple implementation, efficient for (quite) small data sets, adaptive (i.e., efficient) for data sets that are already substantially sorted: the time complexity is O(nk) when each element in the input is no more than k places away from its sorted position, and stable (i.e., does not change the relative order of elements with equal keys).
1 2 3 4 5 6 7 8 9 10 11 12 13
{
"arr": "[12, 11, 13, 5, 6]",
"n": 5
}Overview
Insertion Sort builds the sorted result one element at a time, the way most people sort a hand of playing cards. It takes the next element (the key), shifts every larger element in the sorted prefix one slot to the right, and drops the key into the gap that opens up.
Because elements are shifted rather than swapped, each step writes only once per moved element. On data that is already nearly sorted, the inner loop stops almost immediately, which is why Insertion Sort is the fastest simple sort in practice and is used inside Tim Sort and Intro Sort for small pieces.
With the default input 12, 11, 13, 5, 6, notice how 5 has to travel all the way to the front, shifting 13, 12 and 11, while 13 does not move at all.
Step by step
- Treat
arr[0]as a sorted prefix of length 1. - Take
key = arr[i]for the next indexi. - Walk
jleft fromi - 1whilearr[j] > key, copyingarr[j]intoarr[j + 1]. - Write
keyintoarr[j + 1], the first position where it is not smaller than its left neighbour. - Repeat for every
iup ton - 1.
Complexity
| Case | Cost | Why |
|---|---|---|
| Best case | O(n) | Already-sorted input: every inner loop stops after one comparison. |
| Average case | O(n^2) | Each key moves about halfway back through the prefix. |
| Worst case | O(n^2) | Reverse-sorted input shifts every key to the front. |
| Extra space | O(1) | Only the key variable is needed. |
When to use it
- Small arrays (roughly under 16–32 elements), where its low overhead beats O(n log n) algorithms.
- Nearly sorted data, or data that arrives one item at a time and must stay sorted (online sorting).
- As the finishing step inside hybrid sorts such as Tim Sort and Intro Sort.
Common mistakes
- Using
>=in the while condition shifts equal elements and breaks stability. - Swapping on every step instead of shifting triples the number of writes for no benefit.
- Forgetting the
j >= 0bound, which readsarr[-1]when the key is the smallest so far.
A dry run is the best way to check your understanding of Insertion Sort: follow each row, predict the next one, and compare. The run below takes 43 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
- 12, 11, 13, 5, 6
- Result
- arr = [5, 6, 11, 12, 13], return value = [5, 6, 11, 12, 13]
| Step | Line | Array | What happens |
|---|---|---|---|
| 1 | 2 | [12, 11, 13, 5, 6] | n = 5 |
| 5 | 6 | [12, 11, 13, 5, 6] | n = 5, i = 1, key = 11, j = 0, condition = 0 >= 0 && 12 > 11 |
| 6 | 7 | [12, 12, 13, 5, 6] | n = 5, i = 1, key = 11, j = 0, arr[j+1] = 12 |
| 8 | 6 | [12, 12, 13, 5, 6] | n = 5, i = 1, key = 11, j = -1, condition = false |
| 9 | 10 | [11, 12, 13, 5, 6] | n = 5, i = 1, key = 11, j = -1, arr[j+1] = 11 |
| 13 | 6 | [11, 12, 13, 5, 6] | n = 5, i = 2, key = 13, j = 1, condition = 1 >= 0 && 12 > 13 |
| 18 | 6 | [11, 12, 13, 5, 6] | n = 5, i = 3, key = 5, j = 2, condition = 2 >= 0 && 13 > 5 |
| 19 | 7 | [11, 12, 13, 13, 6] | n = 5, i = 3, key = 5, j = 2, arr[j+1] = 13 |
| 21 | 6 | [11, 12, 13, 13, 6] | n = 5, i = 3, key = 5, j = 1, condition = 1 >= 0 && 12 > 5 |
| 22 | 7 | [11, 12, 12, 13, 6] | n = 5, i = 3, key = 5, j = 1, arr[j+1] = 12 |
| 24 | 6 | [11, 12, 12, 13, 6] | n = 5, i = 3, key = 5, j = 0, condition = 0 >= 0 && 11 > 5 |
| 25 | 7 | [11, 11, 12, 13, 6] | n = 5, i = 3, key = 5, j = 0, arr[j+1] = 11 |
| 27 | 6 | [11, 11, 12, 13, 6] | n = 5, i = 3, key = 5, j = -1, condition = false |
| 28 | 10 | [5, 11, 12, 13, 6] | n = 5, i = 3, key = 5, j = -1, arr[j+1] = 5 |
| 32 | 6 | [5, 11, 12, 13, 6] | n = 5, i = 4, key = 6, j = 3, condition = 3 >= 0 && 13 > 6 |
| 33 | 7 | [5, 11, 12, 13, 13] | n = 5, i = 4, key = 6, j = 3, arr[j+1] = 13 |
| 35 | 6 | [5, 11, 12, 13, 13] | n = 5, i = 4, key = 6, j = 2, condition = 2 >= 0 && 12 > 6 |
| 36 | 7 | [5, 11, 12, 12, 13] | n = 5, i = 4, key = 6, j = 2, arr[j+1] = 12 |
| 38 | 6 | [5, 11, 12, 12, 13] | n = 5, i = 4, key = 6, j = 1, condition = 1 >= 0 && 11 > 6 |
| 39 | 7 | [5, 11, 11, 12, 13] | n = 5, i = 4, key = 6, j = 1, arr[j+1] = 11 |
| 41 | 6 | [5, 11, 11, 12, 13] | n = 5, i = 4, key = 6, j = 0, condition = 0 >= 0 && 5 > 6 |
| 42 | 10 | [5, 6, 11, 12, 13] | n = 5, i = 4, key = 6, j = 0, arr[j+1] = 6 |
| 43 | 12 | [5, 6, 11, 12, 13] | return value = [5, 6, 11, 12, 13] |