author avatar BooleanStack

Bubble Sort

Bubble sort (sometimes called sinking sort) is usually the first sorting algorithm you'll encounter when learning to code. It's simple, easy to wrap your head around, stable, and in-place. The catch? Its quadratic time complexity makes it painfully slow for large datasets.

Bubble Sort

Bubble sort (sometimes called sinking sort) is usually the first sorting algorithm you’ll encounter when learning to code. It’s simple, easy to wrap your head around, stable, and in-place. The catch? Its quadratic time complexity makes it painfully slow for large datasets. But here’s the thing—understanding bubble sort gives you a solid mental model for how comparison-based sorting actually works: swaps, passes, and complexity analysis.


Real-World Analogy

Real-World Analogy: Picture a line of people standing in random order. You want them arranged from shortest to tallest. Someone walks down the line comparing each pair of neighbors. If the person on the left is taller, they swap places. After one complete walk-through, the tallest person will have “bubbled up” to the far right. Keep repeating this process, and eventually everyone stands in perfect height order. That’s bubble sort in a nutshell.


How Bubble Sort Works (Core Idea)

At its heart, bubble sort repeatedly scans through the array and swaps neighbors that are out of order.

For an array of length n (sorting in ascending order):

  1. Start at index 0.
  2. Compare arr[j] and arr[j + 1].
  3. If arr[j] > arr[j + 1], swap them.
  4. Move j forward until you hit the end of the unsorted portion.
  5. After the first pass? The maximum element is guaranteed to be sitting at index n - 1.
  6. Rinse and repeat. Each pass lets you stop one step earlier since the largest elements have already bubbled to their final spots.

After k passes, the last k elements are locked in place.

Key Concept: Bubble sort only swaps adjacent elements. This is what makes it stable (equal elements keep their relative order) and dead simple to implement in-place.


Visualizing Basic Bubble Sort

Basic Pass-by-Pass Behavior

Use this interactive visualizer to watch how basic (non-optimized) bubble sort moves through an array, pass by pass and swap by swap.

Bubble Sort Visualizer

Click 'Start Sort' to begin
64
0
34
1
25
2
12
3
22
4
11
5
90
6
Comparisons
0
Swaps
0
Current Index
-
Sorted Until
All

How Bubble Sort Works

  1. Compare adjacent elements in the array
  2. If they are in wrong order (left > right), swap them
  3. Continue through the array until the end
  4. The largest element "bubbles up" to the end
  5. Repeat for remaining unsorted elements
  6. Stop when no swaps are needed in a complete pass

As you step through it, notice:


Step-by-Step Example

Let’s sort [5, 3, 8, 4, 2] in ascending order using the basic algorithm.

Pass 1 (compare indices 0 to 3):

  1. Compare (5, 3) → swap → [3, 5, 8, 4, 2]
  2. Compare (5, 8) → no swap needed → [3, 5, 8, 4, 2]
  3. Compare (8, 4) → swap → [3, 5, 4, 8, 2]
  4. Compare (8, 2) → swap → [3, 5, 4, 2, 8]
    Result: The max element 8 is now locked at the end.

Pass 2 (compare indices 0 to 2):

  1. Compare (3, 5) → already good
  2. Compare (5, 4) → swap → [3, 4, 5, 2, 8]
  3. Compare (5, 2) → swap → [3, 4, 2, 5, 8]
    Result: 5 is now fixed at index 3.

Pass 3 (compare indices 0 to 1):

  1. Compare (3, 4) → looks good
  2. Compare (4, 2) → swap → [3, 2, 4, 5, 8]
    Result: 4 is locked at index 2.

Pass 4 (compare index 0):

  1. Compare (3, 2) → swap → [2, 3, 4, 5, 8]

Done. Array sorted.


Optimized Bubble Sort (Early Exit)

The basic version has a glaring inefficiency—it keeps running passes even after the array’s already sorted. We can fix this with a simple trick: exit early if no swaps happen.

The Strategy:

This single optimization drops the best-case time complexity from O(n²) down to O(n) (when the input’s already sorted).

See the Optimization in Action

Optimized Bubble Sort

500ms
45
[0]
23
[1]
67
[2]
12
[3]
89
[4]
34
[5]
56
[6]
Passes
0
Comparisons
0
Swaps
0
Sorted
0
Optimized
No

Optimizations Applied

1. Early Termination

If no swaps occur in a pass, the array is already sorted

2. Reduced Range

After each pass, the largest unsorted element is in its final position

3. Last Swap Position

Elements after the last swap are already sorted

Try running the optimized version on:

You’ll see that for sorted or nearly sorted inputs, it stops after just a few passes. But for reverse-sorted arrays? It still grinds through all those quadratic comparisons.


Implementation (Java, C++, Python)

Here’s production-ready, optimized bubble sort in three languages.

public class BubbleSort {

    public static void sort(int[] arr) {
        int n = arr.length;
        boolean swapped;

        // Outer loop runs at most n-1 passes
        for (int i = 0; i < n - 1; i++) {
            swapped = false;

            // Last i elements are already in place
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    // Swap adjacent elements
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                }
            }

            // If no elements were swapped, array is sorted
            if (!swapped) {
                break;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {64, 34, 25, 12, 22, 11, 90};
        sort(arr);

        System.out.print("Sorted array: ");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

Implementation notes:


Complexity Analysis

Time Complexity

Time Complexity: Bubble sort clocks in at O(n²) for average and worst cases because of those nested loops. It only hits O(n) on sorted input when you’ve got the early-exit optimization in place.

Space Complexity

Other Properties


Comparing Bubble Sort to Other Algorithms

In the real world, bubble sort gets absolutely crushed by O(n log n) algorithms like Quicksort, Mergesort, or Timsort (Python’s built-in sort).

Use this visualization to see how bubble sort’s performance tanks compared to efficient alternatives as your dataset grows.

Bubble Sort: Basic vs Optimized

300ms

Basic Bubble Sort

0
Passes
0
Comparisons
0
Swaps

Optimized Bubble Sort

0
Passes
0
Comparisons
0
Swaps

Key Differences

Basic Version

  • Always completes n-1 passes
  • No early termination
  • Fixed number of comparisons
  • Simple but inefficient

Optimized Version

  • Stops early if sorted
  • Tracks last swap position
  • Reduces comparison range
  • More efficient on partially sorted data

What you’ll typically see:


When (and Why) You Might Use Bubble Sort

Look, you shouldn’t reach for bubble sort in production for anything beyond trivial data sizes. But it’s still useful in specific situations:

  1. Education and Interviews:

    • It’s the perfect teaching tool for comparison-based sorting.
    • Great baseline for discussing complexity, stability, and in-place algorithms.
  2. Tiny Collections:

    • For extremely small arrays where performance doesn’t matter, bubble sort gives you a compact, stable solution. (Though honestly, Insertion Sort is usually the better pick here.)
  3. Nearly Sorted Data:

    • If you know your array’s almost sorted, the optimized version can actually be pretty fast (O(n)).
  4. Restricted Environments:

    • In embedded systems or teaching environments where code memory is tight and n is small, the simplicity can be a genuine advantage.

Common Pitfalls and Edge Cases

Edge Cases and Pitfalls:

  1. Inner Loop Bounds: Forget to subtract i in the inner loop (n - i - 1) and you’ll waste time re-comparing already sorted elements.
  2. Missing Optimization: Skip the swapped flag and your best-case stays at O(n²). Ouch.
  3. Off-by-one Errors: Using j <= n - i - 1 instead of j < n - i - 1 will cause an out-of-bounds crash when checking arr[j+1].
  4. Descending Order: Flip the comparison by accident (< instead of >) and suddenly you’re sorting in reverse.

Optimization Tips and Variants

Bubble Sort is inherently O(n²), but you can squeeze out some improvements:

  1. Shrinking Inner Loop: Always use n - i - 1 to skip the sorted tail.
  2. Cocktail Shaker Sort: A bidirectional variant that alternates left-to-right and right-to-left passes. This helps move small elements stuck at the end (the infamous “turtles”) to the front faster. Still O(n²) though.
  3. Knowing When to Switch: For anything beyond toy examples, if you need a simple O(n²) algorithm, Insertion Sort is usually faster in practice because it does fewer writes.

Practical Tip: Think of bubble sort as your gateway drug. Once you’re comfortable with it, move on to insertion sort, then selection sort, and finally tackle quicksort or mergesort to see how they compare.


Summary and Key Takeaways

Mastering bubble sort isn’t about using it in real projects. It’s about building a rock-solid foundation in how sorting actually works under the hood. Once you’ve got that down, you’ll find it way easier to understand and implement more sophisticated algorithms.

Similar Posts