Skip to content

Bubble sort

Swapping neighbours that are out of order carries the largest remaining value to the end on each pass, and a pass with no swaps ends the sort.

Helps to know first
This topic

First, the picture

Compare each pair of neighbours and swap them if they are out of order. Watch the largest value ride to the end.

The largest value bubbles to the end

Ten numbers, neighbours compared and swapped

void bubble_sort(int *a, int n){    for (int end = n - 1; end > 0; end--) {        bool swapped = false;        for (int i = 0; i < end; i++) {            comparisons++;            if (a[i] > a[i + 1]) {                int t = a[i];                a[i] = a[i + 1];                a[i + 1] = t;                swaps++;                swapped = true;            }        }        if (!swapped)            break;    }}

main has started: a has room for ten ints.

pass
–
comparisons
0
swaps
0

Output

0.00 / 30.36 s
Describe this picture

Ten bars in a row, the cells of int a[10], each as tall as its value: 6 2 9 1 5 10 3 8 4 7, with the cell numbers 0 to 9 above them. The code pane beside the picture shows bubble_sort, with the line about to run marked. The clip takes about 30 seconds. For each comparison, two neighbouring bars are tinted, with the marker i under the left one. When the left bar is taller, the two slide past each other. The first pass plays slowly: 10 rides all the way from cell 5 to cell 9, and its bar greys, sorted. Each later pass is quicker, and the grey tail at the right grows by one bar each time. The sixth pass compares 1 2 3 4 5 and swaps nothing, so the sort stops and every bar greys. Under the picture are one sentence on the current step and the readouts “pass”, “comparisons” and “swaps”, which end at 6, 39 and 20. The transport plays and pauses, steps one beat back or forward, and scrubs; a paused step is kept in the page address as bubble-sort.step.

Neighbours, swapped

Walk along the array comparing each value with the next one. If the left one is larger, swap them. The largest value is then swapped at every comparison it takes part in, so it is carried to the last cell: after one pass it is in its final place. The next pass can stop one cell earlier, and carries the second largest to the cell before the last. Each pass places one more value at the end.

Other values move too. In the first pass on 6 2 9 1 5 10 3 8 4 7, 2 swaps with 6, and 9 moves right until it meets 10. Every value with a larger value anywhere before it moves one place left. That is why a pass can find the array already sorted before the last pass is due.

The code and its cost

void bubble_sort(int *a, int n)
{
    for (int end = n - 1; end > 0; end--) {
        bool swapped = false;
        for (int i = 0; i < end; i++) {
            comparisons++;
            if (a[i] > a[i + 1]) {
                int t = a[i];
                a[i] = a[i + 1];
                a[i + 1] = t;
                swaps++;
                swapped = true;
            }
        }
        if (!swapped)
            break;
    }
}

end is the last cell of the part not yet sorted. The inner loop compares a[i] with a[i + 1] for i from 0 to end − 1, and swaps a pair that is out of order through t. swapped records whether the pass changed anything. If it did not, every neighbouring pair is in order, so the whole array is, and the sort stops early.

Counting the work

A pass over the first end + 1 cells makes end comparisons. Without the early stop, the passes make 9 + 8 + … + 1 = 45 comparisons on ten values, and n(n − 1)/2 on n. On the house array, bubble.c stops after 6 passes: 9 + 8 + 7 + 6 + 5 + 4 = 39 comparisons. The first five passes swap; the sixth only confirms that nothing is out of order. It prints 39 comparisons, 20 swaps.

Swaps are inversions

An inversion is a pair of values in the wrong order: a larger one somewhere before a smaller one. The house array has 20 of them. A swap exchanges two neighbours that are in the wrong order, and changes no other pair’s order, so every swap removes exactly one inversion. The sort ends with none left, so it made exactly 20 swaps, whatever the order of its passes.

The number of passes has a reason too. A pass moves a value left by at most one place. 4 has five larger values before it (6, 9, 5, 10 and 8), so it needs five passes that swap before it reaches its place; then one more pass finds nothing to do.

Three properties for the whole chapter

Every sort in this chapter is judged on the same three questions.

  • In place: it needs only a fixed amount of extra memory, here one int t, whatever n is.
  • Stable: values that are equal keep their order. Bubble sort swaps only when a[i] > a[i + 1], so two equal values are never swapped past each other.
  • Adaptive: it is faster on input that is nearly sorted. With the early stop, a sorted array costs one pass of n − 1 comparisons and no swaps.

The worst case is a reversed array: every pair is an inversion, n(n − 1)/2 of them, so it makes n(n − 1)/2 swaps and as many comparisons. That is O(n²), and the early stop does not change it. It helps only when the input is nearly sorted.

Worked example

The first pass. On 6 2 9 1 5 10 3 8 4 7, the first pass swaps 6 and 2, then 9 and 1, 9 and 5, then 10 with 3, 8, 4 and 7, giving 2 6 1 5 9 3 8 4 7 10. 10 is in its place.

Reversed and sorted. bubble-cases.c runs the same function on 10 9 8 … 1: 45 comparisons and 45 swaps, the worst case, since all 45 pairs are inversions. On 1 2 … 10 it makes 9 comparisons and no swaps: one pass, then the early stop.

Two checks. How many inversions does 3 1 2 have? (2: 3 before 1 and 3 before 2.) If the test were a[i] >= a[i + 1], would the sort still be stable? (No: two equal neighbours would be swapped.)

Where it’s used

Teaching. Bubble sort is the simplest sort to state and to check by hand, and its counts are a baseline: every other sort in this chapter makes fewer comparisons or fewer swaps on the same ten values, starting with Insertion sort.

Nearly sorted data. A single pass with the early stop confirms that an array is sorted in n − 1 comparisons, and fixes a few neighbours that are out of order.

Reference card

Code or ideaMeaning
one passcompare a[i], a[i + 1] for i below end; swap if out of order
after pass kthe k largest values are in their places at the end
early stopa pass with no swap: the array is sorted
inversiona pair in the wrong order; each swap removes one
comparisonsn(n − 1)/2 at worst, n − 1 on sorted input
swapsthe number of inversions
in place, stable, adaptiveyes, yes, yes

Platform: C11, gcc on x86-64 Linux: int 4 bytes, pointers 8, little-endian. Addresses in the pictures are short stand-ins, by one rule for the whole course; sizes are the real ones.

End of the lesson

Where to go next.

New lessons by email

Are you 13 or over?

Accounts and email updates are for people aged 13 or over. We keep only your answer, never your date of birth.

Phasorium

Account

Sign inWith Google, GitHub or your email

Subjects

Site

Look