Beginner 8 min · March 05, 2026

Bubble Sort — Why 50K Items Took 12 Minutes in Production

Bubble Sort on 50K transaction IDs triggered 1.

N
Naren · Founder
Plain-English first. Then code. Then the interview question.
About
Quick Answer
  • Bubble Sort repeatedly compares adjacent elements and swaps them if out of order
  • After each pass, the largest unsorted value "bubbles" to its final position at the end
  • Always use the swapped flag to break early on already-sorted arrays — O(n) best case instead of O(n²)
  • Space complexity is O(1); sorting happens in-place with one temp variable
  • Not suitable for large datasets — 50 million comparisons for 10k elements worst-case
  • The only real production use: tiny (≤20 items) or nearly-sorted lists where simplicity wins

Sorting is one of the most fundamental operations in computing. Every time you see a leaderboard ranked by score, a contact list ordered alphabetically, or search results sorted by relevance, a sorting algorithm did that work. Understanding how sorting works under the hood is one of the first things that separates developers who just write code from developers who understand it. Bubble Sort is where that journey starts for most people — and for good reason.

Before Bubble Sort existed as a named concept, programmers faced a gnarly problem: given a random list of numbers, how do you systematically put them in order without missing anything or scrambling what you've already fixed? Bubble Sort solves this with one beautifully simple rule — repeatedly compare neighboring elements and swap them if they're in the wrong order. No element gets overlooked, and the process guarantees that after enough passes, every element is exactly where it belongs.

By the end of this article you'll be able to explain Bubble Sort out loud without looking at notes, trace through any array step-by-step on paper, write a clean working implementation in Java from memory, spot the optimized version that makes it smarter, and answer the interview questions that trip most beginners up. Let's build this from the ground up.

How Bubble Sort Actually Works — One Pass at a Time

Let's use a concrete example. Say you have this array of five numbers: [5, 3, 8, 1, 4]. Your job is to sort it smallest to largest.

Bubble Sort works in rounds called 'passes'. During each pass, you walk through the array from left to right, look at every pair of neighboring elements side by side, and ask one question: 'Is the left one bigger than the right one?' If yes, swap them. If no, move on.

After Pass 1 on [5, 3, 8, 1, 4]
  • Compare 5 and 3 → 5 > 3, swap → [3, 5, 8, 1, 4]
  • Compare 5 and 8 → 5 < 8, no swap → [3, 5, 8, 1, 4]
  • Compare 8 and 1 → 8 > 1, swap → [3, 5, 1, 8, 4]
  • Compare 8 and 4 → 8 > 4, swap → [3, 5, 1, 4, 8]

Notice what happened: the largest number, 8, has 'bubbled up' all the way to its correct position at the end. That's the magic. Each pass guarantees the largest unsorted number finds its final home. You repeat this process, and each pass needs to go one element shorter because the last element is already locked in.

Visual Pass-By-Pass Diagram

The diagram below tracks our example array [5, 3, 8, 1, 4] through each pass. Each row shows the state of the array after the row's pass. The highlighted element is the one that has 'bubbled' into its final sorted position. Notice how the largest element moves to the rightmost unsorted slot each pass. This visualisation helps cement the mental model of Bubble Sort as a series of sinking the largest remaining value.

The Optimized Version — Stop Early When the Array Is Already Sorted

The basic version has a silent problem. Imagine your array is [1, 2, 3, 4, 5] — already sorted. The basic algorithm still ploughs through all the passes anyway, making zero swaps but wasting time. With a large dataset, that's painfully inefficient.

The fix is elegant: use a flag called 'swapped'. At the start of each pass, set it to false. If you make even one swap during a pass, flip it to true. At the end of the pass, check the flag. If it's still false — meaning you walked through the entire array and didn't swap a single pair — the array is already sorted. Stop immediately.

This optimization doesn't change Bubble Sort's worst-case performance (we'll talk about that shortly), but it dramatically improves its best-case. On an already-sorted array, it now takes just one pass instead of n-1 passes. This is the version you should always write — it shows you understand the algorithm, not just the mechanics.

It also makes Bubble Sort one of the few simple algorithms that can detect a sorted array in O(n) time, which is occasionally useful in practice when you expect your data to be nearly sorted.

Time and Space Complexity — What the Big-O Numbers Actually Mean

Big-O notation sounds intimidating but it's just a way of asking: 'How much slower does this algorithm get as the input gets bigger?' Let's work through Bubble Sort's numbers intuitively.

Imagine you have 10 elements. In the worst case (reverse-sorted order like [10, 9, 8, 7...]), Pass 1 does 9 comparisons, Pass 2 does 8, Pass 3 does 7... all the way down to 1. Total comparisons: 9+8+7+6+5+4+3+2+1 = 45. For 100 elements that's roughly 4,950 comparisons. For 1,000 elements, about 499,500. The number of comparisons grows with the square of the input size — that's O(n²).

Bubble Sort's three cases
  • Best Case O(n): Array is already sorted. With the optimized version, one pass, no swaps, done.
  • Average Case O(n²): Randomly ordered data. Lots of passes, lots of swaps.
  • Worst Case O(n²): Reverse-sorted data. Maximum comparisons and swaps every pass.

Space complexity is O(1) — constant. You're sorting the array in-place using only one temporary variable for swaps, regardless of how big the array is. That's actually a genuine strength of Bubble Sort.

For small arrays (say, fewer than 20 elements) or nearly-sorted data, Bubble Sort is perfectly fine. For large datasets, it's genuinely slow compared to Merge Sort O(n log n) or Quick Sort O(n log n) — and you'd never use it in production on big data.

Sorting Strings and Real Objects — Bubble Sort Isn't Just for Numbers

Everything we've done so far sorted integers, but in the real world you'll sort names, products, grades — anything. Bubble Sort's comparison step is the only thing that changes. For strings, Java's compareTo() method does the heavy lifting: it returns a negative number if the first string comes before the second alphabetically, zero if they're equal, and a positive number if it comes after.

This is a great moment to understand what 'sorting' really means. The algorithm itself — the passes, the comparisons, the swaps — stays identical. Only the definition of 'which one is bigger' changes. This is why sorting algorithms are often taught with Comparators in production code: you separate the sorting logic from the comparison logic cleanly.

Sorting strings alphabetically is also a great way to cement your understanding because you can verify the output easily in your head. Try tracing through the passes yourself on paper before running the code — that's genuinely the fastest way to make this algorithm stick in your memory.

Python and C++ Implementations

Bubble Sort is language-agnostic — the same logic translates directly to Python and C++. Below is a Python implementation with the swapped flag. In C++, the syntax changes slightly: use std::vector or arrays, and the swap can be done with std::swap or a manual temp. The key differences: Python uses range and list indexing, while C++ uses for loops and std::swap. Both exhibit O(n²) worst-case and O(n) best-case with early exit.

A C++ version would look similar: iterate over indices, compare arr[i] > arr[i+1], and use std::swap(arr[i], arr[i+1]). The early-exit flag works identically.

Recursive Bubble Sort and Cocktail Sort — Variations That Expand Your Understanding

Bubble Sort is almost always implemented iteratively, but it can also be written recursively. The recursive version reduces the problem size by one each call — the largest element bubbles to the end, then you call recursively on the rest of the array. It's not more efficient, but it's a great exercise in thinking recursively about algorithms.

Another practical variant is Cocktail Sort (a.k.a. Shaker Sort). Instead of always moving left to right, Cocktail Sort alternates direction — it goes left to right, then right to left, then left to right again. This helps when the smallest elements are near the end of the array. In standard Bubble Sort, a small value at the end takes many passes to move all the way left. Cocktail Sort handles that in one back-and-forth sweep.

Cocktail Sort is still O(n²) worst-case, but it can cut the number of passes in half on certain inputs (e.g., an array where the first half is sorted descending and the second half is sorted ascending). It's worth knowing about because interviewers sometimes ask: 'How would you improve Bubble Sort without changing the fundamental approach?'

Advantages and Disadvantages of Bubble Sort

Bubble Sort, despite its poor large-scale performance, has specific strengths that make it useful in limited contexts.

Advantages: - Simplicity: The algorithm is easy to understand, implement, and debug. It's often the first sorting algorithm taught. - In-place: Uses O(1) extra space — only a single temp variable for swapping. - Stable: Preserves the relative order of equal elements. Important for multi-key sorts. - Adaptive with optimization: The swapped flag makes it O(n) on already-sorted data. - Detects sorted arrays: It can stop early, which no comparably simple sort like Selection Sort can do.

Disadvantages: - Slow on large data: O(n²) time complexity makes it impractical for arrays beyond a few hundred elements. - Many swaps: Even when elements are only slightly out of place, many swaps occur, increasing overhead. - Rarely used in practice: Production systems rely on O(n log n) algorithms (Quick Sort, Merge Sort, TimSort). - Not efficient for modern hardware: Cache-unfriendly due to many traversals of the entire array.

Advantages and Disadvantages Table

Here is a concise table summarizing the pros and cons of Bubble Sort:

AdvantageDescription
SimplicityEasy to understand and implement.
In-place sortingO(1) extra space.
StabilityMaintains relative order of equal elements.
AdaptiveO(n) best case with early exit flag.
DisadvantageDescription
Slow on large dataO(n²) time complexity.
Many swapsInefficient on modern hardware.
Rarely usedBuilt-in sorts are preferred.

Applications — When to Accept O(n²)

Bubble Sort's O(n²) complexity is a dealbreaker for large datasets, but there are specific scenarios where its simplicity outweighs the cost:

  • Very small n (≤20 elements): The absolute runtime for O(n²) on 20 elements is negligible (≈190 comparisons). The simplicity and low overhead justify using it.
  • Nearly sorted data: If you know the data is almost in order (e.g., a list that had a few insertions), bubble sort with early exit runs in roughly O(n) because few swaps are needed.
  • Educational purposes: Teaching the concept of sorting, pass-by-pass visualisation, and algorithm analysis. No other sort illustrates the mechanics as cleanly.
  • Embedded systems: When code size is constrained and you need a simple, small sort routine for tiny arrays.

In all other cases, use a built-in sort (O(n log n)). A good rule of thumb: if the array fits on one line of code (say, under 30 elements), Bubble Sort is acceptable. Otherwise, reach for Arrays.sort(), sorted(), or similar.

Bubble Sort vs Selection Sort
AspectBubble SortSelection Sort
Best-case timeO(n) — with early exit flagO(n²) — always scans full array
Worst-case timeO(n²)O(n²)
Space complexityO(1) — in-placeO(1) — in-place
Number of swapsHigh — swaps at every out-of-order pairLow — at most one swap per pass
Stable sort?Yes — equal elements keep original orderNo — can swap equal elements past each other
Detects sorted array?Yes — with the swapped flag optimizationNo — always runs all passes
Best real-world useNearly sorted small arraysWhen minimising writes/swaps matters most

Key Takeaways

  • Bubble Sort repeatedly compares adjacent pairs and swaps them if out of order — the largest unsorted element 'bubbles' to its correct position at the end of each pass.
  • Always include the 'swapped' early-exit flag. Without it, you have O(n²) best case. With it, you have O(n) best case — a critical difference on nearly-sorted data.
  • Bubble Sort is O(n²) in the average and worst case, making it impractical for large datasets — but its O(1) space complexity and simplicity make it a perfect teaching algorithm and fine for tiny arrays.
  • Bubble Sort is stable: equal elements never swap past each other, which means their original relative order is preserved — a property that matters when sorting objects by multiple fields.
  • Cocktail Sort (shaker sort) is a variant that alternates direction, reducing passes on certain inputs while remaining O(n²).
  • In production, never use Bubble Sort for arrays greater than about 20 elements — use Arrays.sort() or a proper O(n log n) algorithm.

Common Mistakes to Avoid

  • Forgetting to shrink the inner loop each pass
    Symptom: The algorithm still works, but you're wastefully re-comparing elements already in their final sorted positions — much slower on large arrays, and can even cause out-of-bounds on the last index because you compare arr[last] with arr[last+1].
    Fix: Make the inner loop condition index < size - pass - 1. The - pass shrinks the window each round. The -1 prevents accessing arr[index+1] past the end.
  • Skipping the 'swapped' early-exit flag
    Symptom: On an already-sorted or nearly-sorted array, the algorithm runs all n-1 passes anyway — showing your interviewer you haven't thought through the best case.
    Fix: Add a boolean swappedThisPass = false before the inner loop, set it to true on any swap, and break out of the outer loop immediately if it's still false after a full pass.
  • Using the wrong comparison operator for descending order
    Symptom: You change `>` to `<` and expect it to sort largest-to-smallest, but you get confused when the logic feels backwards.
    Fix: Think of it as 'if the left element is smaller than the right, they're in the wrong order for descending sort' — so array[index] < array[index + 1] is correct for descending. Rename your variable to make the intent clear: boolean wantDescending = true; and comment the comparison direction.
  • Not understanding stable sort implications
    Symptom: When sorting objects by multiple fields (e.g., first by grade, then by name), Bubble Sort's stability preserves the order of equal elements, but if you write an unstable sort manually, you'll scramble secondary sorts.
    Fix: Recognise that Bubble Sort's stability is a feature: it only swaps when left > right. If left == right, no swap, so original order is kept. Use this property when writing multi-key sorts.

Interview Questions on This Topic

  • QWhat is the time complexity of Bubble Sort in the best, average, and worst case — and what input triggers each?JuniorReveal
    Best case: O(n) when the array is already sorted and you use the swapped flag (one pass, zero swaps). Average case: O(n²) for random data. Worst case: O(n²) when the array is reverse-sorted (maximum comparisons and swaps every pass). The comparison count is roughly n²/2 in the worst case. Interview tip: Always mention the swapped flag when discussing best case — it shows you know the optimisation, not just the textbook number.
  • QHow would you modify Bubble Sort to stop early if the array is already sorted, and why does that optimization matter?JuniorReveal
    Add a boolean flag swapped initialized to false before each pass. Set it to true if any swap occurs. After each pass, if swapped is still false, break out of the outer loop — the array is fully sorted. This matters because without it, Bubble Sort always completes n-1 passes even on sorted data, wasting O(n²) comparisons. With early exit, the best case drops to O(n). This optimisation costs nothing in the worst case (still O(n²)) and is expected in any professional-quality Bubble Sort implementation.
  • QIs Bubble Sort a stable sorting algorithm? What does 'stable' mean, and why does it matter when sorting objects by one field?Mid-levelReveal
    Yes, Bubble Sort is stable. Stability means that equal elements retain their original relative order after sorting. Because Bubble Sort only swaps elements that are strictly > (not >=), equal elements never cross each other. Stability matters when you sort objects by one field after having sorted by another — for example, sorting a list of employees first by department, then by name. A stable sort on the second key (name) preserves the primary sort (department). If Bubble Sort were unstable, the department order could be scrambled.
  • QCan you implement Bubble Sort recursively? How does the approach compare to the iterative version?SeniorReveal
    Yes. The recursive version does one pass (placing the largest element at the end), then calls itself on the subarray arr[0..n-2]. Base case: when n ≤ 1, return. Recursive Bubble Sort has the same time complexity but uses O(n) extra stack space instead of O(1) in the iterative version. It's not used in practice but is a good interview exercise to test understanding of both recursion and Bubble Sort. Example (Java): ``java void recursiveBubbleSort(int[] arr, int n) { if (n <= 1) return; boolean swapped = false; for (int i = 0; i < n - 1; i++) { if (arr[i] > arr[i + 1]) { swap(arr, i, i + 1); swapped = true; } } if (!swapped) return; recursiveBubbleSort(arr, n - 1); } ``

Frequently Asked Questions

Is bubble sort ever actually used in real software?

Rarely. Bubble Sort is primarily used as a teaching tool because its mechanics are easy to visualise. In production code you'd use language-built-in sorts like Java's Arrays.sort(), which uses a highly optimised Dual-Pivot Quicksort under the hood. The one exception: Bubble Sort with an early-exit flag is occasionally useful for tiny, nearly-sorted arrays where its simplicity and O(n) best case are valuable.

Why is it called Bubble Sort?

Because larger elements gradually 'bubble up' toward the end of the array over successive passes, just like air bubbles rise through water. After each pass, the largest remaining unsorted element has floated into its correct final position at the top of the unsorted portion.

What's the difference between a pass and a comparison in Bubble Sort?

A 'pass' is one full sweep of the inner loop from the start of the unsorted portion to its end. During each pass, you make multiple individual 'comparisons' — one for each neighboring pair you examine. An array of n elements requires up to n-1 passes, and each pass makes multiple comparisons, so the total comparison count grows quadratically.

Can Bubble Sort be made adaptive to nearly-sorted data?

Yes — the swapped flag optimisation makes it adaptive. If the array becomes sorted mid-way, Bubble Sort terminates in the next pass. Additionally, you can keep track of the last swap position: after a pass, all elements after that position are already sorted, so the next pass can stop even earlier. This is sometimes called 'optimised Bubble Sort' and can cut passes significantly on nearly-sorted data.

How does Bubble Sort compare to Insertion Sort for small arrays?

Insertion Sort generally performs better than Bubble Sort on small arrays because it does fewer swaps. Insertion Sort shifts elements rather than swapping, making it about 2-3x faster on random small arrays. However, for nearly-sorted data, both are fast. Many production sorting algorithms (like TimSort) use Insertion Sort for small runs because of its efficiency.

🔥

That's Sorting. Mark it forged?

8 min read · try the examples if you haven't

Previous
A* Search Algorithm
1 / 8 · Sorting
Next
Selection Sort