A simple sorting algorithm that repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order. The pass through the list is repeated until the list is sorted.
1 2 3 4 5 6 7 8 9 10 11 12 13
{
"arr": "[5, 3, 8, 4, 2]",
"n": 5
}Overview
Bubble Sort walks along the array comparing each pair of neighbours. Whenever the left value is bigger than the right one, the two are swapped. After one full pass, the largest value has been carried — bubbled — all the way to the last position, where it stays for good.
Each later pass can therefore stop one position earlier, because the tail of the array is already final. That is why the inner loop in the code runs to n - i - 1 rather than to the end of the array.
In the visualizer, watch the two highlighted bars on every comparison step. With the default input 5, 3, 8, 4, 2 the value 8 reaches the end after the first pass, 5 settles next, and so on until no out-of-order pair is left.
Step by step
- Start at index 0 and compare
arr[j]witharr[j + 1]. - If
arr[j] > arr[j + 1], swap them; otherwise leave them alone. - Move one position right and repeat until the end of the unsorted part.
- The largest unsorted value is now in its final place, so shrink the unsorted part by one.
- Repeat passes until the unsorted part has a single element (or, in the optimised version, until a pass makes no swaps).
Complexity
| Case | Cost | Why |
|---|---|---|
| Best case | O(n) | Only with the early-exit flag: one pass over sorted input finds no swaps and stops. The version shown here always does every pass, so it is O(n^2) even on sorted data. |
| Average case | O(n^2) | About n^2/2 comparisons, and on random data roughly half of them lead to a swap. |
| Worst case | O(n^2) | Reverse-sorted input makes every comparison a swap. |
| Extra space | O(1) | Swaps happen in place using a single temporary variable. |
When to use it
- Teaching and interviews: it is the easiest sort to trace by hand, which makes it a good warm-up for reasoning about loop invariants.
- Tiny or almost-sorted arrays where code size matters more than speed, and only with the early-exit optimisation.
- Checking whether an array is already sorted: one optimised pass answers that in O(n).
Common mistakes
- Off-by-one errors in the inner loop: running
jup ton - 1reads past the sorted tail and, in some languages, past the array. - Using
>=instead of>in the comparison swaps equal elements and silently makes the sort unstable. - Forgetting that the textbook version has no early exit, so it never benefits from sorted input.
A dry run is the best way to check your understanding of Bubble 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
- 5, 3, 8, 4, 2
- Result
- arr = [2, 3, 4, 5, 8], return value = [2, 3, 4, 5, 8]
| Step | Line | Array | What happens |
|---|---|---|---|
| 1 | 2 | [5, 3, 8, 4, 2] | n = 5 |
| 4 | 5 | [5, 3, 8, 4, 2] | n = 5, i = 0, j = 0, comparison = 5 > 3 |
| 6 | 7 | [3, 3, 8, 4, 2] | n = 5, i = 0, j = 0, temp = 5, arr[j] = 3 |
| 7 | 8 | [3, 5, 8, 4, 2] | n = 5, i = 0, j = 0, temp = 5, arr[j+1] = 5 |
| 9 | 5 | [3, 5, 8, 4, 2] | n = 5, i = 0, j = 1, comparison = 5 > 8 |
| 11 | 5 | [3, 5, 8, 4, 2] | n = 5, i = 0, j = 2, comparison = 8 > 4 |
| 13 | 7 | [3, 5, 4, 4, 2] | n = 5, i = 0, j = 2, temp = 8, arr[j] = 4 |
| 14 | 8 | [3, 5, 4, 8, 2] | n = 5, i = 0, j = 2, temp = 8, arr[j+1] = 8 |
| 16 | 5 | [3, 5, 4, 8, 2] | n = 5, i = 0, j = 3, comparison = 8 > 2 |
| 18 | 7 | [3, 5, 4, 2, 2] | n = 5, i = 0, j = 3, temp = 8, arr[j] = 2 |
| 19 | 8 | [3, 5, 4, 2, 8] | n = 5, i = 0, j = 3, temp = 8, arr[j+1] = 8 |
| 22 | 5 | [3, 5, 4, 2, 8] | n = 5, i = 1, j = 0, comparison = 3 > 5 |
| 24 | 5 | [3, 5, 4, 2, 8] | n = 5, i = 1, j = 1, comparison = 5 > 4 |
| 26 | 7 | [3, 4, 4, 2, 8] | n = 5, i = 1, j = 1, temp = 5, arr[j] = 4 |
| 27 | 8 | [3, 4, 5, 2, 8] | n = 5, i = 1, j = 1, temp = 5, arr[j+1] = 5 |
| 29 | 5 | [3, 4, 5, 2, 8] | n = 5, i = 1, j = 2, comparison = 5 > 2 |
| 31 | 7 | [3, 4, 2, 2, 8] | n = 5, i = 1, j = 2, temp = 5, arr[j] = 2 |
| 32 | 8 | [3, 4, 2, 5, 8] | n = 5, i = 1, j = 2, temp = 5, arr[j+1] = 5 |
| 35 | 5 | [3, 4, 2, 5, 8] | n = 5, i = 2, j = 0, comparison = 3 > 4 |
| 37 | 5 | [3, 4, 2, 5, 8] | n = 5, i = 2, j = 1, comparison = 4 > 2 |
| 39 | 7 | [3, 2, 2, 5, 8] | n = 5, i = 2, j = 1, temp = 4, arr[j] = 2 |
| 40 | 8 | [3, 2, 4, 5, 8] | n = 5, i = 2, j = 1, temp = 4, arr[j+1] = 4 |
| 43 | 5 | [3, 2, 4, 5, 8] | n = 5, i = 3, j = 0, comparison = 3 > 2 |
| 45 | 7 | [2, 2, 4, 5, 8] | n = 5, i = 3, j = 0, temp = 3, arr[j] = 2 |
| 46 | 8 | [2, 3, 4, 5, 8] | n = 5, i = 3, j = 0, temp = 3, arr[j+1] = 3 |
| 47 | 11 | [2, 3, 4, 5, 8] | return value = [2, 3, 4, 5, 8] |