Chapter 17: Elementary Sorting Algorithms
17.02Beginner / Intermediate5 topics14 min1 interactive animation

Bubble sort

Bubble sort repeatedly walks the array and swaps neighbours that are out of order. After each pass the largest remaining value has bubbled to the end. It is rarely used in production, but it is the clearest introduction to sorting invariants.

Learning goals

  • Trace bubble sort pass by pass
  • Add the early-exit optimisation and explain its O(n) best case
  • Count comparisons and swaps and relate swaps to inversions
  • Explain why bubble sort is stable

Prerequisites

ArraysNested loopsSwapping two variables
17.02.1

Repeated adjacent swaps

Compare arr[j] with arr[j + 1] and swap them if the left one is larger. One full pass carries the largest value to the right end, like a bubble rising.

Invariant: after pass p, the last p + 1 positions hold the largest values in their final order, so the inner loop can stop at n - 1 - pass.

Bubble sort

Interactive · edit the input

Your input

Try

int[] arr · length 7

38
27
43
3
9
82
10
0123456
Being comparedMovedSorted
Setup

Repeatedly compare neighbours and swap them when they are out of order. Large values bubble to the right.

Step 1 / 43
Java
1public static void bubbleSort(int[] arr) {
2 int n = arr.length;
3 for (int pass = 0; pass < n - 1; pass++) {
4 boolean swapped = false;
5 for (int j = 0; j < n - 1 - pass; j++) {
6 if (arr[j] > arr[j + 1]) {
7 int tmp = arr[j];
8 arr[j] = arr[j + 1];
9 arr[j + 1] = tmp;
10 swapped = true;
11 }
12 }
13 if (!swapped) break; // early exit: already sorted
14 }
15}

Live state

0 comparisons0 swaps

n

7

No condition evaluated on this step
Execution trace (dry run table)Show 43 steps
StepLineStateWhat happens
1L2n=7Repeatedly compare neighbours and swap them when they are out of order. Large values bubble to the right.
2L4n=7 pass=0 swapped=falsePass 1: after it, index 6 will hold its final value.
3L6pass=0 j=0 swapped=falseOut of order, swap them.
4L8pass=0 j=0 swapped=trueSwapped: arr[0] = 27, arr[1] = 38.
5L6pass=0 j=1 swapped=trueAlready in order, leave them. Equal values never swap, which keeps bubble sort stable.
6L6pass=0 j=2 swapped=trueOut of order, swap them.
7L8pass=0 j=2 swapped=trueSwapped: arr[2] = 3, arr[3] = 43.
8L6pass=0 j=3 swapped=trueOut of order, swap them.
9L8pass=0 j=3 swapped=trueSwapped: arr[3] = 9, arr[4] = 43.
10L6pass=0 j=4 swapped=trueAlready in order, leave them. Equal values never swap, which keeps bubble sort stable.
11L6pass=0 j=5 swapped=trueOut of order, swap them.
12L8pass=0 j=5 swapped=trueSwapped: arr[5] = 10, arr[6] = 82.
13L13pass=0 swapped=true82 is now fixed at index 6. Swaps happened, so run another pass.
14L4n=7 pass=1 swapped=falsePass 2: after it, index 5 will hold its final value.
15L6pass=1 j=0 swapped=falseAlready in order, leave them. Equal values never swap, which keeps bubble sort stable.
16L6pass=1 j=1 swapped=falseOut of order, swap them.
17L8pass=1 j=1 swapped=trueSwapped: arr[1] = 3, arr[2] = 38.
18L6pass=1 j=2 swapped=trueOut of order, swap them.
19L8pass=1 j=2 swapped=trueSwapped: arr[2] = 9, arr[3] = 38.
20L6pass=1 j=3 swapped=trueAlready in order, leave them. Equal values never swap, which keeps bubble sort stable.
21L6pass=1 j=4 swapped=trueOut of order, swap them.
22L8pass=1 j=4 swapped=trueSwapped: arr[4] = 10, arr[5] = 43.
23L13pass=1 swapped=true43 is now fixed at index 5. Swaps happened, so run another pass.
24L4n=7 pass=2 swapped=falsePass 3: after it, index 4 will hold its final value.
25L6pass=2 j=0 swapped=falseOut of order, swap them.
26L8pass=2 j=0 swapped=trueSwapped: arr[0] = 3, arr[1] = 27.
27L6pass=2 j=1 swapped=trueOut of order, swap them.
28L8pass=2 j=1 swapped=trueSwapped: arr[1] = 9, arr[2] = 27.
29L6pass=2 j=2 swapped=trueAlready in order, leave them. Equal values never swap, which keeps bubble sort stable.
30L6pass=2 j=3 swapped=trueOut of order, swap them.
31L8pass=2 j=3 swapped=trueSwapped: arr[3] = 10, arr[4] = 38.
32L13pass=2 swapped=true38 is now fixed at index 4. Swaps happened, so run another pass.
33L4n=7 pass=3 swapped=falsePass 4: after it, index 3 will hold its final value.
34L6pass=3 j=0 swapped=falseAlready in order, leave them. Equal values never swap, which keeps bubble sort stable.
35L6pass=3 j=1 swapped=falseAlready in order, leave them. Equal values never swap, which keeps bubble sort stable.
36L6pass=3 j=2 swapped=falseOut of order, swap them.
37L8pass=3 j=2 swapped=trueSwapped: arr[2] = 10, arr[3] = 27.
38L13pass=3 swapped=true27 is now fixed at index 3. Swaps happened, so run another pass.
39L4n=7 pass=4 swapped=falsePass 5: after it, index 2 will hold its final value.
40L6pass=4 j=0 swapped=falseAlready in order, leave them. Equal values never swap, which keeps bubble sort stable.
41L6pass=4 j=1 swapped=falseAlready in order, leave them. Equal values never swap, which keeps bubble sort stable.
42L13pass=4 swapped=falseThis pass made no swaps, so the array is sorted. Exit early: this is why the best case is O(n).
43L15Sorted with 20 comparisons, 11 swaps.
17.02.2

Early-exit optimization

If a whole pass makes no swaps, every neighbouring pair is in order, so the array is sorted. A swapped flag lets the algorithm stop immediately.

Without the flag, bubble sort always does n(n-1)/2 comparisons. With it, already sorted input takes a single pass of n - 1 comparisons. Run the “Already sorted” preset to see this.

17.02.3

Dry run

Sorting [5, 1, 4, 2, 8]. Each row is one pass; ↔ marks a swap.

  • Total: 9 comparisons and 4 swaps.
  • 4 swaps equals the number of inversions in the input: (5,1), (5,4), (5,2), (4,2).
PassComparisons in orderArray after passSwaps
15↔1, 5↔4, 5↔2, 5 vs 8[1, 4, 2, 5, 8]3
21 vs 4, 4↔2, 4 vs 5[1, 2, 4, 5, 8]1
31 vs 2, 2 vs 4[1, 2, 4, 5, 8]0, early exit
17.02.4

Complexity

Every swap fixes exactly one inversion, so swaps equal the number of inversions: 0 for sorted input, n(n-1)/2 for reverse sorted input.

Comparisons are n(n-1)/2 in the worst case. With early exit, the best case is one pass.

Best

O(n)

Average

O(n²)

Worst

O(n²)

Space

O(1)

17.02.5

Stability

Bubble sort swaps only when arr[j] > arr[j + 1], strictly greater. Equal neighbours are never swapped, so equal keys never pass each other and the sort is stable.

Changing the test to >= would still sort correctly but would break stability. Try the “Duplicates” preset and watch the a/b tags.

Practice ladder

Now try it yourself

Easy

  • Bubble sort descending
  • Count the swaps bubble sort makes on an input

Medium

  • Implement the last-swap-position optimisation
  • Bubble sort a singly linked list by swapping values

Advanced

  • Prove that bubble sort's swap count equals the inversion count
  • Find the minimum adjacent swaps to sort a permutation

Key takeaways

  • Adjacent swaps move the largest remaining value to the end on each pass.
  • Early exit gives an O(n) best case; average and worst are O(n²).
  • Strict comparison keeps it stable; swaps equal the number of inversions.