Bubble Sort

Imagine a line of pupils standing in a jumbled order, and you want them shortest-to-tallest. You can't see the whole line at once, so you use a simple rule: look at just two people standing next to each other, and if the taller one is in front, ask them to swap places. Then shuffle one step along and check the next pair. Keep sweeping down the line, again and again, and — almost like magic — everyone drifts into order.

That is bubble sort, one of the first sorting algorithms every computer scientist meets. Its whole idea is built from one tiny action repeated over and over:

The name comes from that last picture: on every pass the biggest remaining value rises to the top of the list like a bubble rising through water.

Watching it bubble

Let's sort the little list [5, 1, 4, 2] into ascending order. Each bar's height is its value, and on every step the two bars being compared are highlighted. Step through it and watch the tall bars drift rightwards to the end:

Notice how the 5 reaches the far right after just the first pass, then the 4 settles into place on the second. Each pass "locks in" one more value at the end, so the part of the list still worth checking gets shorter every time.

The swap: why you need a temporary box

The heart of bubble sort is swapping two values. You might think you can just write a = b and b = a — but that loses one of the values! The moment you copy b into a, the old a is gone, so b = a just copies b back onto itself. You end up with two copies of b and no a at all.

The fix is a temporary variable — a spare box to hold one value while you move the other. It's exactly like swapping the drinks in two glasses: you need a third, empty glass to pour one into first. Run this and see the swap work correctly:

let a: number = 5; let b: number = 1; console.log("Before: a =", a, " b =", b); const temp = a; // stash a in the spare box a = b; // now a can safely take b's value b = temp; // and b takes the stashed value console.log("After: a =", a, " b =", b);

Bubble sort in code

Now we put the pieces together. We need an inner loop that makes one pass, comparing each adjacent pair list[j] and list[j + 1] and swapping when they're out of order, wrapped in an outer loop that repeats those passes. Run it and read the console.log after each pass — you'll see the largest values marching to the right:

function bubbleSort(list: number[]): number[] { for (let i = 0; i < list.length - 1; i++) { // outer loop: one pass each for (let j = 0; j < list.length - 1 - i; j++) { // inner loop: walk the adjacent pairs if (list[j] > list[j + 1]) { // is this pair in the wrong order? const temp = list[j]; // classic three-line swap list[j] = list[j + 1]; list[j + 1] = temp; } } console.log("After pass " + (i + 1) + ":", list.join(", ")); } return list; } bubbleSort([5, 1, 4, 2, 8, 3]);

Two details make it efficient. The inner loop stops at length - 1 - i, not length - 1: because pass i has already parked the i largest values at the end, there's no point re-checking them. And the comparison uses >, so equal values are left alone — which keeps the sort stable (a nice bonus you'll meet again later).

Stopping early when it's already sorted

There's one more trick that makes bubble sort clever rather than plodding. If a whole pass goes by without a single swap, the list must already be in order — so we can stop right away instead of grinding through the remaining passes. We track this with a swapped flag:

function bubbleSort(list: number[]): number[] { for (let i = 0; i < list.length - 1; i++) { let swapped = false; // did we swap anything this pass? for (let j = 0; j < list.length - 1 - i; j++) { if (list[j] > list[j + 1]) { const temp = list[j]; list[j] = list[j + 1]; list[j + 1] = temp; swapped = true; // yes — remember it } } console.log("After pass " + (i + 1) + ":", list.join(", ")); if (!swapped) { // a clean pass → already sorted console.log("No swaps — the list is sorted, stopping early."); break; } } return list; } bubbleSort([1, 2, 5, 3, 4]); // nearly sorted — it should finish quickly

Try feeding it a list that's already sorted, like [1, 2, 3, 4, 5]: it makes just one pass, sees no swaps, and stops immediately. That "best case" is the fastest bubble sort ever gets.

Bubble sort is wonderfully easy to understand — but it is slow. For a list of n items it makes roughly n \times n = n^2 comparisons in the worst case (about \tfrac{1}{2}n(n-1), to be exact). That's fine for a handful of values, but it grows brutally: sorting 10 items takes about 45 comparisons, but 1000 items takes around half a million, and a million items takes hundreds of billions. Real software sorting big lists uses far faster algorithms (like merge sort or quicksort). Bubble sort is a teaching tool, brilliant for learning how sorting works — not the one you'd reach for on a big job.

The other classic trap is the swap itself. If you try to exchange two values with just list[j] = list[j + 1] followed by list[j + 1] = list[j], you overwrite and lose one value — both slots end up holding the same number. Always use a temporary variable (the three-line swap above) so nothing is thrown away.