Sorting Algorithms Studies: Bubble Sort

Lately, I decided to revise on some subjects that I studied a long time ago. One of these subjects is sorting algorithms. And, by studying it, I thought that creating a material explaining these algorithms could be helpful. Yeah, it’s one more person talking about this, but different people have different visions, and looking through other perspectives is always a good thing.

The first article on this subject will be about the first sorting algorithm that people learn, usually: Bubble Sort.

Explanation

This algorithm works by repeatedly comparing the current value with the next value, and swapping them if the next value is lower than the current value; or, if the sorting is being done in decrescent order, if the next value is higher than the current value. Having provided the clarifications, from now on this article will focus on the crescent order implementation.

Some say that the name comes from the fact that, as it happens with the bubbles, that rise to the top in the water, so it happens too to list elements with greater values, which are recurrently pushed to the end (top) of the list.

Structure

It is comprised by two nested loops:

  • The outer one loops amongst the numbers that comprise the range between 0 and the size of the array, minus 2. Example: if the array has size 5, the outer loop will loop from 0 to 3. Let’s call the number of the outer loop x.
  • The inner loop is the one that actually makes the comparisons and swaps. It loops amongst the numbers that comprise the range between 0 and the length of the array, minus 2, minus the number of the outer loop (x). Example: if the array has size 5, the inner loop will loop from 0 to 3 on the first outer loop, 0 to 2 in the second outer loop, and so on. Let’s call the number of the inner loop y.
  • For each y in the inner loop, it compares the element on the index y with the element on the index y + 1. If the first is greater than the second, the elements are swapped.

Also, there is an optimized Bubble Sort implementation. Basically, for each outer loop, a swapped flag is set to False. If there is any swap in an inner loop, swapped is set to True. At the end of the last inner loop, if swapped is False, it means that the array is sorted and no more outer loops are needed, so the outer loop can be ended prematurely and the array can be returned.

Code

This is the implementation of Bubble Sort in Python. It may look slighter more complex than the usual Bubble Sort implementation, but that’s because I’ll to provide codes that work both for the crescent and decrescent sorting.

And this is the implementation of optimized Bubble Sort in Python. Again, this codes works both for the crescent and decrescent sorting.

Finally, here’s the interactive algorithm visualization, with step-by-step execution.

Complexity

Worst-case performance: O(n²)

Best-case performance: O(n²) for the normal implementation; O(n) for the optimized implementation

Average performance: O(n²)

Space complexity 1: O(n)

Auxiliary space 2: O(1) for the normal implementation; O(2) for the optimized implementation. 3

Benchmark

As the posts from the Sorting Algorithms Studies are posted, I’ll benchmark the algorithms against each other. For now, there’s only Bubble Sort to be shown.

Sorting 1000 different arrays with 1000 randomly sorted elements
Algorithm Average Time Spent (seconds)
Crescent Decrescent
Bubble Sort 0.1692 0.1692
Bubble Sort Optimized 0.1704 0.1702

Sorting 1000 different arrays with 1000 elements in ascending order
Algorithm Average Time Spent (seconds)
Crescent Decrescent
Bubble Sort Optimized 0.0002 0.2563
Bubble Sort 0.0985 0.2519

Sorting 1000 different arrays with 1000 elements in descending order
Algorithm Average Time Spent (seconds)
Crescent Decrescent
Bubble Sort Optimized 0.2435 0.0001
Bubble Sort 0.2373 0.0890

Wrapping Up

Bubble Sort is a simple algorithm, easy to understand and implement. It doesn’t performs well, but it may be enough for some scenarios, like when you have really small lists of when there’s not much time to make a better implementation (like in a hackaton).

Stay tuned for the next chapters of this series!

  1. Auxiliary Space + Input space

  2. Extra or temporary space used by the algorithm during it's execution.

  3. Python's way of swapping two values dismisses the need of a temp variable to make the swap of values. Because of that, there is no use of auxiliary space in Python for the normal implementation. However, the optimized implementation still uses O(1) auxiliary space.