Step through one of the most intuitive sorting algorithms where larger elements "bubble up" to the end.
Parameters
12
Visualization
Step: 0
Click Randomize or Step to begin sorting.
Algorithm Insight
Bubble Sort repeatedly swaps adjacent elements if they are in the wrong order.
1.Compare two adjacent elements.
2.If $Left > Right$, swap them.
3.Move to the next pair.
4.After one pass, the largest element is at the end.
Complexity
Average CaseO(N²)
Space ComplexityO(1)
Overview
Bubble Sort is a simple sorting algorithm that repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order. The pass through the list is repeated until the list is sorted. The algorithm gets its name because smaller or larger elements "bubble" to their proper place.
The Core Idea: Compare and Swap
The entire algorithm is built on one fundamental operation: comparing two adjacent items and swapping them if the first is larger than the second. This process is repeated from the beginning of the array to the end. After the first full pass, the largest element in the array will have "bubbled up" to the very last position. The next pass does the same for the second-largest element, and so on.
Swapping neighbours until nothing moves
Bubble sort compares each adjacent pair and swaps them if they are out of order. One pass moves the largest remaining element to the end — it "bubbles up". Repeat until a pass makes no swaps.
Sorting [5, 1, 4, 2]:
Pass
Comparisons
Result
1
5>1 swap, 5>4 swap, 5>2 swap
[1, 4, 2, 5]
2
1<4 no, 4>2 swap, 4<5 no
[1, 2, 4, 5]
3
No swaps — stop
[1, 2, 4, 5]
def bubble_sort(arr):
n = len(arr)
for i in range(n):
swapped = False
for j in range(n - 1 - i): # -i: the tail is already sorted
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True
if not swapped:
break # already sorted; stop early
return arr
Two details make this the "optimised" version. The - i skips the sorted tail, halving the comparisons. The swapped flag stops at once on sorted input, giving O(n) in the best case.
Why it is slow
Case
Complexity
When
Best
O(n)
Already sorted — one pass, no swaps
Average
O(n²)
Random order
Worst
O(n²)
Reverse sorted
Space
O(1)
In place
The problem is that each swap moves an element by exactly one position. An element at the wrong end of the array needs n swaps to reach its place, and with n such elements the total work is quadratic.
Compare with insertion sort, which does the same number of comparisons in the worst case and typically fewer swaps, or with shell sort. This is bubble-like but compares elements far apart first so they travel quickly.
The practical numbers: at n = 10,000 bubble sort does about 50 million comparisons; Timsort does about 130,000. On a modern machine that is roughly a second against a few milliseconds.
Exploration guide
One Full Pass: Click "Randomize Array", then click "Next Step" repeatedly. Watch the two active bars (the ones being compared). Notice how the larger value always moves to the right after a swap. After you've gone through the whole array once, observe that the largest bar is now at the far right, in its final sorted position.
The Sorted Section: As you complete each full pass, you'll see the sorted elements build up at the end of the array. The algorithm is smart enough to know it doesn't need to check this sorted section again, making each subsequent pass slightly shorter.
Performance & When to Use It
Bubble Sort has a time cost of O(n²) in the average and worst cases. This is very slow for large datasets. Its main advantages are its ease and the fact that it requires O(1) extra space.
Because of its poor performance, Bubble Sort is rarely used in production systems. It serves primarily as a teaching tool for sorting concepts and algorithm analysis.
Common mistakes with Bubble Sort
Omitting the early-exit flag, which loses the O(n) best case for no benefit.
Omitting - i, which re-compares the already-sorted tail every pass.
Using >= instead of >, which swaps equal elements and destroys stability.
Off-by-one in the inner range, reading arr[j+1] past the end.
Using it on real data.sorted() is Timsort in C and is faster by orders of magnitude.
Continue with insertion sort, which builds on this idea.
Run it in Python
One line printed per pass, so you can watch the largest value reach the end of the list on pass one and stay there. The second run shows what the early exit is worth.
bubble_sort.pyPython 3
# Bubble sort: repeatedly swap adjacent items that are out of order.
def bubble_sort(a):
a = a[:] # copy, so the original stays printable
n = len(a)
passes = swaps = 0
for i in range(n - 1):
passes += 1
swapped = False
for j in range(n - 1 - i): # the last i items are already final
if a[j] > a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
swaps += 1
swapped = True
print(f"pass {passes}: {a}")
if not swapped: # a clean pass means it is sorted
break
return a, passes, swaps
data = [5, 1, 4, 2, 8, 0, 2]
print("start :", data)
out, passes, swaps = bubble_sort(data)
print("sorted:", out)
print(f"{passes} passes, {swaps} swaps")
print()
print("already sorted:")
_, p, s = bubble_sort([0, 1, 2, 4, 5, 8])
print(f"{p} pass, {s} swaps - the early exit makes the best case O(n)")
print()
print("reversed (the worst case):")
_, p, s = bubble_sort([8, 5, 4, 2, 1, 0])
print(f"{p} passes, {s} swaps")
Output
How the code works
for j in range(n - 1 - i):The - i is the optimisation that makes bubble sort worth writing. After pass i the last i items are in final position, so re-scanning them is pure waste.
a[j], a[j + 1] = a[j + 1], a[j]Python's tuple assignment evaluates the right side first, so this is a genuine swap. In most languages it needs a temporary variable, and forgetting it overwrites one of the two values.
if not swapped: breakA whole pass with nothing out of order proves the list is sorted. This single flag turns the best case from O(n²) into O(n) — and it is the only reason bubble sort beats selection sort on nearly-sorted input.
swapsThe swap count equals the number of inversions in the input, exactly. That is a real property, not an approximation: each swap fixes one inverted pair and no more.
Change one thing
Sort [1, 2, 3, 4, 5, 0]. One small value at the wrong end costs a full n passes — bubble sort moves items left one position per pass, and that is its real weakness.
Delete - i from the inner range. The result stays correct and the swap count is unchanged; only the wasted comparisons go up.
Change > to >=. Still sorted, but equal items now get swapped — the sort is no longer stable.
Where this runs
Real CPython, compiled to WebAssembly and running on your own machine — nothing is uploaded. The first run takes a few seconds while the interpreter downloads; after that it is immediate. Need more room, or want to paste your own attempt? Use the Python compiler.
Predict, then reveal
About to run: One Full Pass. Before it does — what happens to the readout?
Committing to an answer first is the point — the reveal runs the experiment on the visualisation above and reads the real value back, so nothing here is scripted.
Check yourself
0 of 3
Answer without scrolling back up.
What does the swapped flag buy?
A pass with no swaps proves the list is sorted, so it stops. Without it, sorted input still costs the full n passes.
Why does the inner loop run to n - 1 - i rather than n - 1?
Each pass carries the largest remaining value to the end, so that tail never needs looking at again. It saves comparisons, not complexity.
The program's swap count for a given list equals:
Each swap fixes exactly one inverted pair, so the totals match exactly. That is why [1,2,3,4,5,0] is so expensive - one item out of place at the wrong end is five inversions.
Cheat sheet
Bubble Sort
Watch adjacent pairs compare and swap, sending the largest value bubbling to the end on every pass through the array.
Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.