Skip to Content
Course content

169: Implementing Bubble Sort and Selection Sort

Click on the "Edit" button in the top corner of the screen to edit your slide content.

When you first start implementing sorting algorithms, it's easy to look at a diagram in a book and think you've got it. But there is a massive difference between an algorithm that is "correct" and one that is "efficient." I've seen plenty of juniors write sorting logic that passes the unit tests but absolutely kills performance in production because they took the most literal, naive path to the solution. Today, let's look at Bubble Sort and Selection Sort through that lens.

The Cost of Blind Iteration in Bubble Sort

Bubble Sort is the classic "first sort" everyone learns. The naive approach is simple: you loop through the array, compare adjacent elements, and swap them if they're in the wrong order. You repeat this process for every single element in the list. If you have 1,000 elements, the naive version will perform roughly a million comparisons, even if the array was already sorted from the start. It's blindly iterating, and in a professional environment, that's a waste of CPU cycles.

// The naive way: always runs O(n^2)
void bubbleSortNaive(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

The better way to handle this is to introduce a "dirty bit" or a swapped flag. Look, if you go through the entire inner loop and don't perform a single swap, it means the array is already sorted. Why keep looping? By adding a simple boolean check, we can turn the best-case scenario from $O(n^2)$ into $O(n)$. It’s a tiny change in code that provides a huge win when dealing with partially sorted data.

// The better way: early exit if sorted
void bubbleSortOptimized(int arr[], int n) {
    bool swapped;
    for (int i = 0; i < n - 1; i++) {
        swapped = false;
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                swapped = true;
            }
        }
        if (!swapped) break; // Exit early!
    }
}

Minimizing the Shuffle in Selection Sort

Selection Sort takes a different approach: it looks for the minimum element in the remaining unsorted part of the array and puts it at the beginning. A common mistake I see—and I'll admit, I did this early in my career—is swapping the elements every time you find a smaller value during the scan. If you do that, you're essentially just doing a slower version of Bubble Sort, hammering your memory with unnecessary write operations.

Memory writes are generally more expensive than reads. The naive approach swaps constantly. The professional approach is to keep track of the index of the minimum value. You scan the rest of the array, update a single integer variable whenever you find a new minimum, and then—and only then—perform one single swap at the end of the outer loop.

// The naive way: swapping too often
void selectionSortNaive(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[i]) {
                // This is a waste! Swapping every time we find a smaller element.
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

Contrast that with the refined version. Here, we only swap once per pass. While Selection Sort is still $O(n^2)$ in all cases (it doesn't have an "early exit" like Bubble Sort), reducing the number of swaps is critical when you're working with large structs or objects where moving data around is costly.

// The better way: tracking the index
void selectionSortOptimized(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int min_idx = i; 
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[min_idx]) {
                min_idx = j; // Just remember where the min is
            }
        }
        // One swap per outer loop iteration
        int temp = arr[min_idx];
        arr[min_idx] = arr[i];
        arr[i] = temp;
    }
}

Choosing Between the Two

So, which one do you actually use? Honestly, in a real-world C project, you'd probably use qsort() from stdlib.h. But if you're constrained to these two, the trade-off is simple: if your data is likely to be "nearly sorted," Bubble Sort with the swapped flag is surprisingly fast. If you're dealing with a system where writing to memory is expensive (like some embedded flash memory), Selection Sort is the winner because it guarantees the minimum number of swaps.




📋 Practical Task

Optimizing a Sensor Data Temperature Log

You have been given a piece of code that sorts temperature readings from a sensor. The current implementation uses a naive Bubble Sort that runs for the full duration of the array, regardless of whether the data is already sorted. This is causing a performance bottleneck on the embedded device.

Your Task: Modify the sortTemperatures function to implement the "early exit" optimization using a flag. Ensure that if the array becomes sorted before all passes are complete, the function returns immediately.

#include <stdio.h>
#include <stdbool.h>

void sortTemperatures(float temps[], int n) {
    // TODO: Implement the optimized Bubble Sort here
    // The current version is naive; make it stop early if no swaps occur.
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (temps[j] > temps[j + 1]) {
                float temp = temps[j];
                temps[j] = temps[j + 1];
                temps[j + 1] = temp;
            }
        }
    }
}

int main() {
    float sensorData[] = {22.5, 21.0, 23.4, 22.1, 20.8};
    int n = 5;

    sortTemperatures(sensorData, n);

    printf("Sorted Temperatures: ");
    for (int i = 0; i < n; i++) {
        printf("%.1f ", sensorData[i]);
    }
    return 0;
}
Rating
0 0

There are no comments for now.

to be the first to leave a comment.