Back to Module 1

Sorting I: Bubble Sort Implementation

Master the fundamentals of sorting algorithms through hands-on implementation of Bubble Sort.

Understanding Bubble Sort

Bubble Sort is one of the simplest sorting algorithms that repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order. While not the most efficient algorithm, it serves as an excellent introduction to sorting concepts and algorithm analysis.

Key Concepts

  • Pairwise comparison and swapping
  • In-place sorting algorithm
  • Time complexity: O(n²)

Learning Objectives

  • Implement basic Bubble Sort
  • Optimize the algorithm
  • Analyze algorithm efficiency

Implementing Bubble Sort

Implementation Steps

  1. 1

    Basic Implementation

    Implement the outer and inner loops for array traversal

    public void bubbleSort(int[] arr) { // Check for null or empty array if (arr == null || arr.length <= 1) { return; // Already sorted } for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - 1 - i; j++) { // Compare adjacent elements if (arr[j] > arr[j + 1]) { // Swap them if they are in wrong order int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } }

    How Bubble Sort Works:

    1. The outer loop runs for (n-1) passes, where n is the array length.
    2. In each pass, the inner loop compares adjacent elements and swaps them if needed.
    3. After each pass, the largest unsorted element "bubbles up" to its correct position.
    4. The inner loop's range decreases with each pass since the largest elements are already in place.
  2. 2

    Optimization

    Add a flag to detect if array is already sorted

    public void optimizedBubbleSort(int[] arr) { // Check for null or empty array if (arr == null || arr.length <= 1) { return; // Already sorted } boolean swapped; for (int i = 0; i < arr.length - 1; i++) { swapped = false; for (int j = 0; j < arr.length - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; swapped = true; } } // If no swapping occurred, array is sorted if (!swapped) break; } }

    Optimization Benefits:

    • Early Termination: If no swaps occur in a pass, the array is already sorted.
    • Best-case Time Complexity: Improved to O(n) for already sorted arrays.
    • Average Performance: Better in practice for partially sorted arrays.
  3. 3

    Algorithm Analysis

    Time Complexity

    • Worst Case: O(n²) - When array is reverse sorted
    • Average Case: O(n²) - For random arrangements
    • Best Case: O(n) - When array is already sorted (optimized version)

    Space Complexity

    • O(1) - Only uses a constant amount of extra space

    When to Use Bubble Sort:

    • Educational purposes to understand sorting concepts
    • Small datasets where simplicity is more important than efficiency
    • Nearly sorted arrays with the optimized version

Visual Example of Bubble Sort

Let's visualize how bubble sort works with the array [5, 3, 8, 4, 2]:

Pass Array State Comparisons & Swaps
Initial [5, 3, 8, 4, 2] -
Pass 1 [3, 5, 4, 2, 8] 5 > 3? Yes, swap [3, 5, 8, 4, 2]
5 > 8? No, keep [3, 5, 8, 4, 2]
8 > 4? Yes, swap [3, 5, 4, 8, 2]
8 > 2? Yes, swap [3, 5, 4, 2, 8]
Pass 2 [3, 4, 2, 5, 8] 3 > 5? No, keep [3, 5, 4, 2, 8]
5 > 4? Yes, swap [3, 4, 5, 2, 8]
5 > 2? Yes, swap [3, 4, 2, 5, 8]
Pass 3 [3, 2, 4, 5, 8] 3 > 5? No, keep [3, 4, 2, 5, 8]
4 > 2? Yes, swap [3, 2, 4, 5, 8]
Pass 4 [2, 3, 4, 5, 8] 3 > 2? Yes, swap [2, 3, 4, 5, 8]
Final [2, 3, 4, 5, 8] Sorted!

Notice how after each pass, the largest unsorted element "bubbles up" to its correct position (highlighted in green).

Common Bubble Sort Variations

1. Bidirectional Bubble Sort (Cocktail Shaker Sort)

This variation traverses the array in both directions, pushing both the largest and smallest values to their correct positions in a single pass.

public void cocktailShakerSort(int[] arr) { boolean swapped; do { swapped = false; // Forward pass (left to right) for (int i = 0; i < arr.length - 1; i++) { if (arr[i] > arr[i + 1]) { int temp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = temp; swapped = true; } } if (!swapped) break; // Array is sorted swapped = false; // Backward pass (right to left) for (int i = arr.length - 2; i >= 0; i--) { if (arr[i] > arr[i + 1]) { int temp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = temp; swapped = true; } } } while (swapped); }

2. Recursive Bubble Sort

A recursive implementation of bubble sort:

public void recursiveBubbleSort(int[] arr, int n) { // Base case if (n == 1) return; // One pass of bubble sort for (int i = 0; i < n - 1; i++) { if (arr[i] > arr[i + 1]) { int temp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = temp; } } // Recursively sort the remaining array recursiveBubbleSort(arr, n - 1); }

Practice Exercises

Exercise 1: Basic Bubble Sort

Implement the basic bubble sort algorithm to sort an array in ascending order.

public void bubbleSort(int[] arr) {
    // Your implementation here
}

Test Cases:

  • [64, 34, 25, 12, 22, 11, 90] → [11, 12, 22, 25, 34, 64, 90]
  • [5, 2, 8, 1, 9] → [1, 2, 5, 8, 9]
  • [1, 2, 3, 4, 5] (already sorted) → [1, 2, 3, 4, 5]

Exercise 2: Optimized Implementation

Implement an optimized version of bubble sort that stops when the array is sorted.

public void optimizedBubbleSort(int[] arr) {
    // Your implementation here
    // Add optimization to break when no swaps needed
}

Test Cases:

  • [1, 2, 3, 5, 4] → Should terminate after one pass!
  • [2, 1, 3, 4, 5] → Should terminate after one pass!
  • [1, 2, 3, 4, 5] → Should terminate immediately!

Exercise 3: Descending Order Sort

Modify the bubble sort algorithm to sort in descending order.

public void bubbleSortDescending(int[] arr) {
    // Your implementation here
    // Sort array in descending order
}

Test Cases:

  • [64, 34, 25, 12, 22, 11, 90] → [90, 64, 34, 25, 22, 12, 11]
  • [5, 2, 8, 1, 9] → [9, 8, 5, 2, 1]

Exercise 4: Implement Cocktail Shaker Sort

Implement the cocktail shaker sort (bidirectional bubble sort) algorithm.

public void cocktailShakerSort(int[] arr) {
    // Your implementation here
    // Sort array using cocktail shaker approach
}

Test Cases:

  • [5, 1, 4, 2, 8, 0, 2] → [0, 1, 2, 2, 4, 5, 8]
  • [3, 2, 1, 4, 5] → [1, 2, 3, 4, 5]

Hint: Traverse the array from left to right, then right to left, in each iteration.

Exercise 5: Count Swaps

Modify the bubble sort algorithm to count and return the number of swaps performed.

public int bubbleSortAndCountSwaps(int[] arr) {
    // Your implementation here
    // Return the number of swaps performed
}

Test Cases:

  • [4, 3, 2, 1] → 6 swaps
  • [1, 3, 2] → 1 swap
  • [1, 2, 3] → 0 swaps

Hint: This is useful to measure how "unsorted" an array is.