Bubble Sort
Written and reviewed by Gagan Bhardwaj · Senior IT Faculty · 15+ years’ experience
Bubble Sort Concept and Loop Invariant
Bubble sort scans adjacent pairs, swaps a pair that is out of order, and repeats passes until no disorder remains. After one complete ascending pass, the largest element in the active range is at its final position. That statement is the pass invariant and explains why the next pass can ignore the sorted suffix.
For ascending order, compare values[i] with values[i+1]; swap only when the first is greater. Each swap removes at least one adjacent inversion.
The result must be ordered and must contain exactly the original elements. This is more important than merely producing the expected output for one example. Compare this elementary method with selection and insertion sort.
Pass-by-Pass Trace
Sort {5, 1, 4, 2, 8} in ascending order:
| Pass | Important swaps | Sequence after pass | Fixed suffix |
|---|---|---|---|
| 1 | 5↔1, 5↔4, 5↔2 | 1 4 2 5 8 | 8 |
| 2 | 4↔2 | 1 2 4 5 8 | 5 8 |
| 3 | None | 1 2 4 5 8 | Whole range sorted |
The third pass makes no swap, so an optimized implementation stops. Without early exit, the output is still correct but needless comparisons continue.
Algorithm and Pseudocode
for end = size down to 2
swapped = false
for i = 0 while i + 1 < end
if values[i] > values[i + 1]
swap the two values
swapped = true
if swapped is false
stopend is exclusive. After a pass, values[end-1] is final, so decreasing end is safe. Empty and one-element ranges require no special branch because the outer loop does not run.
Complete Optimized Bubble Sort Program
#include <iostream>
#include <utility>
#include <vector>
void bubble_sort(std::vector<int>& values) {
for (std::size_t end = values.size(); end > 1; --end) {
bool swapped = false;
for (std::size_t i = 0; i + 1 < end; ++i) {
if (values[i] > values[i + 1]) {
std::swap(values[i], values[i + 1]);
swapped = true;
}
}
if (!swapped) {
break;
}
}
}
int main() {
std::vector<int> values{5, 1, 4, 2, 8};
bubble_sort(values);
std::cout << "Sorted:";
for (int value : values) {
std::cout << ' ' << value;
}
std::cout << '\n';
}The function accepts the vector by non-const reference because it intentionally modifies the caller's data. std::size_t matches container sizes, and the end > 1 guard avoids unsigned underflow.
Early Exit and Last-Swap Optimization
The swapped flag changes the best case from quadratic work to one linear pass. A further refinement remembers the position of the last swap: everything after that position was already ordered, so the next active range can end there.
std::size_t end = values.size();
while (end > 1) {
std::size_t last_swap = 0;
for (std::size_t i = 1; i < end; ++i) {
if (values[i - 1] > values[i]) {
std::swap(values[i - 1], values[i]);
last_swap = i;
}
}
end = last_swap;
}This can reduce comparisons on partially sorted data, but it does not change the Θ(n²) average and worst-case growth.
Complexity, Stability and Correctness
| Property | Optimized bubble sort |
|---|---|
| Best time | Θ(n), already sorted |
| Average time | Θ(n²) |
| Worst time | Θ(n²), reverse-like order |
| Auxiliary space | O(1) |
| Stable | Yes with strict > comparison |
| Adaptive | Yes, with early exit |
Correctness follows from two facts: each pass fixes the largest active element, and swaps preserve the multiset of input values. When a pass makes no swap, every adjacent pair is nondecreasing; by transitivity, the whole range is sorted.
When to Use Bubble Sort
Bubble sort is valuable for visualizing invariants, swaps, stability and asymptotic analysis. It may be acceptable for a tiny range, a classroom demonstration, or code where adjacent exchanges are the exact subject being studied. It is a poor default for large arrays.
| Need | Better choice |
|---|---|
| General fast in-memory sorting | std::sort |
| Preserve equivalent-element order | std::stable_sort |
| Predictable Θ(n log n) teaching algorithm | Merge sort |
| Small/nearly sorted sequence | Insertion sort is often more practical |
Also study the STL algorithms guide before writing a custom production sorter.
Common Mistakes, Tests and Practice
| Mistake | Correction |
|---|---|
Inner loop reaches i == end-1 | Require i+1 < end |
Resetting swapped inside inner loop | Reset once per pass |
Using >= | Use strict > to retain stability |
| Unsigned loop decrements below zero | Use an explicit end > 1 condition |
| Claiming O(n) without early exit | State which implementation is analyzed |
Test set: empty, one element, sorted, reverse sorted, all equal, duplicates, negative values and a large random range. Practice: count comparisons and swaps; implement descending order; implement the last-swap boundary; verify stability using records with equal keys.
Authoritative References
The definition, complexity classification and standard-library comparison were checked against these sources. Continue with sorting and searching in C++.
Bubble Sort का Concept और Invariant
Bubble sort adjacent elements compare करता है, गलत order वाले pair को swap करता है और passes दोहराता है। Ascending pass के बाद active range का largest element final position पर पहुंच जाता है; अगला pass sorted suffix को छोड़ सकता है।
values[i] > values[i+1] होने पर ही swap करें। Strict comparison equal records का relative order बचाता है।
Selection और insertion से तुलना के लिए यह lesson पढ़ें।
Pass-by-Pass Trace
| Pass | Swaps | Pass के बाद sequence |
|---|---|---|
| 1 | 5↔1, 5↔4, 5↔2 | 1 4 2 5 8 |
| 2 | 4↔2 | 1 2 4 5 8 |
| 3 | कोई नहीं | 1 2 4 5 8 |
तीसरे pass में swap नहीं हुआ, इसलिए optimized algorithm तुरंत stop करता है।
Algorithm
हर pass में active range के adjacent pairs compare करें
out-of-order pair swap करें
pass के बाद end एक position घटाएं
किसी pass में swap न हो तो stop करेंEmpty और single-element vector में loop नहीं चलता, इसलिए result natural रूप से सही रहता है।
Complete C++ Program
void bubble_sort(std::vector<int>& values) {
for (std::size_t end = values.size(); end > 1; --end) {
bool swapped = false;
for (std::size_t i = 0; i + 1 < end; ++i) {
if (values[i] > values[i + 1]) {
std::swap(values[i], values[i + 1]);
swapped = true;
}
}
if (!swapped) break;
}
}Full program में <iostream>, <utility> और <vector> include करें। Reference parameter caller के vector को in-place sort करता है।
Early-Exit Optimization
हर outer pass से पहले swapped=false करें। Swap होने पर true करें। Pass के अंत में false रहे तो सभी adjacent pairs ordered हैं, इसलिए best case Θ(n) हो जाता है। Last swap का index रखकर अगला boundary और छोटा किया जा सकता है, पर worst case Θ(n²) ही रहता है।
Complexity और Stability
| Property | Result |
|---|---|
| Best | Θ(n), early exit के साथ |
| Average/Worst | Θ(n²) |
| Extra space | O(1) |
| Stable | हाँ, strict > पर |
| In-place | हाँ |
Swap input elements को खोता या बनाता नहीं। हर pass largest active value fix करता है; no-swap pass पूरे sequence के ordered होने का प्रमाण है।
कब Use करें
Teaching, visualization और tiny inputs में उपयोगी है। Large general data के लिए std::sort, stable order के लिए std::stable_sort, और Θ(n log n) अध्ययन के लिए merge sort बेहतर हैं। STL algorithms भी पढ़ें।
Mistakes, Testing और Practice
i+1 < endरखें, वरना out-of-bounds access होगा।swappedएक pass में एक बार reset करें।- Stability के लिए
>=नहीं,>लें। - Sorted, reverse, duplicates, negative, empty और one-element cases test करें।
Practice: comparisons/swaps count करें, descending version लिखें और equal-key records से stability verify करें।
Authoritative संदर्भ
Definition और complexity इन sources से verify की गई हैं। अगला topic: sorting और searching।