Bubble sort
1
8.3 Description
Suppose we have an array of data which is
unsorted:
Starting at the front, traverse the array, find the
largest item, and move (or bubble) it to the top
With each subsequent iteration, find the next largest
item and bubble it up towards the top of the array
Bubble sort
2
8.3 Description
As well as looking at good algorithms, it is often
useful too look at sub-optimal algorithms
Bubble sort is a simple algorithm with:
a memorable name, and
a simple idea
It is also significantly worse than insertion sort
Bubble sort
3
8.3.1 Implementation
The default algorithm:
template <typename Type>
void bubble( Type *const array, int const n ) {
for ( int i = n - 1; i > 0; --i ) {
for ( int j = 0; j < i; ++j ) {
if ( array[j] > array[j + 1] ) {
std::swap( array[j], array[j + 1] );
}
}
}
}
Bubble sort
4
8.3.1 The Basic Algorithm
Here we have two nested loops, and therefore
calculating the run time is straight-forward:
n 1 n n 1 n n 1
n k n n 1
k 1 2
2
(n 2 )
Bubble sort
5
8.3.1 Example
Consider the unsorted array to
the right
We start with the element in
the first location, and move
forward:
if the current and next items are
in order, continue with the next
item, otherwise
swap the two entries
Bubble sort
6
8.3.1 Example
After one loop, the largest
element is in the last location
Repeat the procedure
Bubble sort
7
8.3.1 Example
Now the two largest elements
are at the end
Repeat again
Bubble sort
8
8.3.1 Example
With this loop, 5 and 7 are
swapped
Bubble sort
9
8.3.1 Example
Finally, we swap the last two
entries to order them
At this point, we have a sorted
array
Bubble sort
10
8.3.2 Implementations and Improvements
The next few slides show some
implementations of bubble sort together with a
few improvements:
reduce the number of swaps,
halting if the list is sorted,
limiting the range on which we must bubble, and
alternating between bubbling up and sinking down
Bubble sort
11
8.3.2.1 First Improvement
We could avoid so many swaps...
template <typename Type>
void bubble( Type *const array, int const n ) {
for ( int i = n - 1; i > 0; --i ) {
Type max = array[0]; // assume a[0]
is the max
for ( int j = 1; j <= i; ++j ) {
if ( array[j] < max ) {
array[j - 1] = array[j]; // move
} else {
array[j – 1] = max; // store the
old max
max = array[j]; // get the
new max
}
}
array[i] = max; // store the
max
}
}
Bubble sort
12
8.3.2.2 Flagged Bubble Sort
One useful modification would be to check if no
swaps occur:
If no swaps occur, the list is sorted
In this example, no swaps occurred
during the 5th pass
Use a Boolean flag to check if no
swaps occurred
Bubble sort
13
8.3.2.2 Flagged Bubble Sort
Check if the list is sorted (no swaps)
template <typename Type>
void bubble( Type *const array, int const n ) {
for ( int i = n - 1; i > 0; --i ) {
Type max = array[0];
bool sorted = true;
for ( int j = 1; j < i; ++j ) {
if ( array[j] < max ) {
array[j - 1] = array[j];
sorted = false;
} else {
array[j – 1] = max;
max = array[j];
}
}
array[i] = max;
if ( sorted ) {
break;
}
}
}
Bubble sort
14
8.3.2.3 Range-limiting Bubble Sort
Intuitively, one may believe that limiting the loops
based on the location of the last swap may
significantly speed up the algorithm
For example, after the second pass,
we are certain all entries after 4 are
sorted
The implementation is easier than that for using
a Boolean flag
Bubble sort
15
8.3.2.3 Range-limiting Bubble Sort
Update i to at the place of the last swap
template <typename Type>
void bubble( Type *const array, int const n ) {
for ( int i = n - 1; i > 0; ) {
Type max = array[0];
int i = 0;
for ( int j = 1; j < i; ++j ) {
if ( array[j] < max ) {
array[j - 1] = array[j];
i = j - 1;
} else {
array[j – 1] = max;
max = array[j];
}
}
array[i] = max;
}
}
Bubble sort
16
8.3.2.3 Range-limiting Bubble Sort
Unfortunately, in practice, this does little to
affect the number of comparisons
Bubble sort
17
8.3.2.4 Alternating Bubble Sort
One operation which does significantly improve
the run time is to alternate between
bubbling the largest entry to the top, and
sinking the smallest entry to the bottom
This does, we will see, make a significant
improvement
Bubble sort
18
8.3.2.4 Alternating Bubble Sort
Alternating between bubbling and sinking:
template <typename Type>
void bubble( Type *const array, int n ) {
int lower = 0;
int upper = n - 1;
while ( true ) {
int new_upper = lower;
for ( int i = lower; i < upper; ++i ) {
if ( array[i] > array[i + 1] ) {
Bubble up to the back
Type tmp = array[i];
array[i] = array[i + 1];
array[i + 1] = tmp;
new_upper = i;
}
}
upper = new_upper;
if ( lower == upper ) {
break;
}
int new_lower = upper;
for ( int i = upper; i > lower; --i ) {
if ( array[i - 1] > array[i] ) {
Type tmp = array[i];
array[i] = array[i - 1]; Sink down to the front
array[i - 1] = tmp;
new_lower = i;
}
}
lower = new_lower;
if ( lower == upper ) {
break;
}
}
}
Bubble sort
19
8.3.2.4 Run-time Analysis
Because the bubble sort simply swaps
adjacent entries, it cannot be any better than
insertion sort which does n + d comparisons
where d is the number of inversions
Unfortunately, it isn’t that easy:
There are numerous unnecessary comparisons
Bubble sort
20
8.3.4 Summary
In this topic, we have looked at bubble sort
From the description, it sounds as if it is as
good as insertion sort
it has the same asymptotic behaviour
in practice, however, it is significantly worse
it is also much more difficult to code...