Sorting Algorithms in Java: Bubble, Selection, Insertion, Merge, and Quick Sort

0 0 0 0 0
author
Shivam Pandey

61 Tutorials


Overview



Introduction to Sorting Algorithms

Sorting is a fundamental operation in computer science that arranges data in a particular order—typically ascending or descending. Efficient sorting is crucial for optimizing performance in searching, data processing, and algorithmic problem-solving. Java provides various sorting algorithms, each with its own advantages and applications.

This tutorial explores Bubble Sort, Selection Sort, Insertion Sort, Merge Sort, and Quick Sort with Java implementations, complexity analysis, comparisons, and real-world applications.


Comparison of Sorting Algorithms

The table below provides a comparison of different sorting algorithms based on time complexity, space complexity, and stability:

Sorting Algorithm

Best Case

Average Case

Worst Case

Space Complexity

Stable?

Bubble Sort

O(n)

O(n²)

O(n²)

O(1)

Yes

Selection Sort

O(n²)

O(n²)

O(n²)

O(1)

No

Insertion Sort

O(n)

O(n²)

O(n²)

O(1)

Yes

Merge Sort

O(n log n)

O(n log n)

O(n log n)

O(n)

Yes

Quick Sort

O(n log n)

O(n log n)

O(n²)

O(log n) (avg.)

No


Sorting Algorithms with Java Implementation

1. Bubble Sort

Bubble Sort is a simple algorithm that repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order. This process repeats until the list is sorted.

Java Implementation:

public class BubbleSort {

    static void bubbleSort(int arr[]) {

        int n = arr.length;

        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;

                }

            }

        }

    }

 

    public static void main(String args[]) {

        int arr[] = {64, 25, 12, 22, 11};

        bubbleSort(arr);

        System.out.println(java.util.Arrays.toString(arr));

    }

}

Time Complexity:

  • Best Case: O(n) (already sorted)
  • Worst & Average Case: O(n²)

Space Complexity: O(1)


2. Selection Sort

Selection Sort repeatedly finds the minimum element from the unsorted portion and swaps it with the first unsorted element.

Java Implementation:

public class SelectionSort {

    static void selectionSort(int arr[]) {

        int n = arr.length;

        for (int i = 0; i < n - 1; i++) {

            int minIndex = i;

            for (int j = i + 1; j < n; j++) {

                if (arr[j] < arr[minIndex]) {

                    minIndex = j;

                }

            }

            int temp = arr[minIndex];

            arr[minIndex] = arr[i];

            arr[i] = temp;

        }

    }

 

    public static void main(String args[]) {

        int arr[] = {64, 25, 12, 22, 11};

        selectionSort(arr);

        System.out.println(java.util.Arrays.toString(arr));

    }

}

Time Complexity:

  • Best, Worst & Average Case: O(n²)

Space Complexity: O(1)


3. Insertion Sort

Insertion Sort builds the sorted array one element at a time by inserting each new element into its correct position.

Java Implementation:

public class InsertionSort {

    static void insertionSort(int arr[]) {

        int n = arr.length;

        for (int i = 1; i < n; i++) {

            int key = arr[i];

            int j = i - 1;

            while (j >= 0 && arr[j] > key) {

                arr[j + 1] = arr[j];

                j--;

            }

            arr[j + 1] = key;

        }

    }

 

    public static void main(String args[]) {

        int arr[] = {64, 25, 12, 22, 11};

        insertionSort(arr);

        System.out.println(java.util.Arrays.toString(arr));

    }

}

Time Complexity:

  • Best Case: O(n)
  • Worst & Average Case: O(n²)

Space Complexity: O(1)


4. Merge Sort

Merge Sort is a divide and conquer algorithm that splits the array into halves, sorts each half, and merges them back.

Java Implementation:

public class MergeSort {

    static void mergeSort(int arr[], int left, int right) {

        if (left < right) {

            int mid = left + (right - left) / 2;

            mergeSort(arr, left, mid);

            mergeSort(arr, mid + 1, right);

            merge(arr, left, mid, right);

        }

    }

 

    static void merge(int arr[], int left, int mid, int right) {

        int n1 = mid - left + 1;

        int n2 = right - mid;

        int leftArray[] = new int[n1];

        int rightArray[] = new int[n2];

 

        System.arraycopy(arr, left, leftArray, 0, n1);

        System.arraycopy(arr, mid + 1, rightArray, 0, n2);

 

        int i = 0, j = 0, k = left;

        while (i < n1 && j < n2) {

            if (leftArray[i] <= rightArray[j]) {

                arr[k] = leftArray[i++];

            } else {

                arr[k] = rightArray[j++];

            }

            k++;

        }

        while (i < n1) arr[k++] = leftArray[i++];

        while (j < n2) arr[k++] = rightArray[j++];

    }

 

    public static void main(String args[]) {

        int arr[] = {64, 25, 12, 22, 11};

        mergeSort(arr, 0, arr.length - 1);

        System.out.println(java.util.Arrays.toString(arr));

    }

}

Time Complexity:

  • Best, Worst & Average Case: O(n log n)

Space Complexity: O(n)


5. Quick Sort

Quick Sort selects a pivot, partitions the array around the pivot, and recursively sorts the partitions.

Java Implementation:

public class QuickSort {

    static void quickSort(int arr[], int low, int high) {

        if (low < high) {

            int pivotIndex = partition(arr, low, high);

            quickSort(arr, low, pivotIndex - 1);

            quickSort(arr, pivotIndex + 1, high);

        }

    }

 

    static int partition(int arr[], int low, int high) {

        int pivot = arr[high];

        int i = low - 1;

        for (int j = low; j < high; j++) {

            if (arr[j] < pivot) {

                i++;

                int temp = arr[i];

                arr[i] = arr[j];

                arr[j] = temp;

            }

        }

        int temp = arr[i + 1];

        arr[i + 1] = arr[high];

        arr[high] = temp;

        return i + 1;

    }

 

    public static void main(String args[]) {

        int arr[] = {64, 25, 12, 22, 11};

        quickSort(arr, 0, arr.length - 1);

        System.out.println(java.util.Arrays.toString(arr));

    }

}

Time Complexity:

  • Best & Average Case: O(n log n)
  • Worst Case: O(n²)

Space Complexity: O(log n)


Final Thoughts

This tutorial provides a comprehensive guide on sorting algorithms, their implementations, and comparisons. Whether you're a beginner or an experienced programmer, mastering sorting algorithms will enhance your problem-solving skills. 🚀


FAQs


Why is Bubble Sort considered inefficient for large datasets?

Bubble Sort repeatedly compares adjacent elements and swaps them if they are in the wrong order. This leads to O(n²) time complexity, making it highly inefficient for large datasets. The excessive number of swaps and comparisons makes it slow compared to Merge Sort (O(n log n)) or Quick Sort (O(n log n)).

2. Why is Quick Sort preferred over Merge Sort in many practical applications?

Quick Sort is preferred in many scenarios because:


  • It has O(n log n) average-case time complexity, which is comparable to Merge Sort.
  • It sorts in-place, meaning it requires O(log n) space on average, whereas Merge Sort requires O(n) extra space.
  • Quick Sort has better cache performance due to its partitioning approach.
    However, in the worst case (O(n²)), Quick Sort can be inefficient, while Merge Sort always guarantees O(n log n) time.

3. Which sorting algorithm is best for nearly sorted data and why?

Insertion Sort is best for nearly sorted data because:


  • It runs in O(n) time when the array is nearly sorted.
  • It requires only a few swaps and comparisons to sort such an array.
  • Unlike Bubble Sort, it does not perform unnecessary swaps, making it faster in practice for small and nearly sorted datasets.

4. What is a stable sorting algorithm, and which algorithms in our list are stable?

A sorting algorithm is stable if it preserves the relative order of elements with equal values.
Stable sorting algorithms in our list:
Bubble Sort
Insertion Sort
Merge Sort
🚫 Selection Sort (can swap elements with the same value)
🚫 Quick Sort (depends on implementation)

5. Can we optimize Bubble Sort? How?

Yes! We can optimize Bubble Sort by introducing a swap flag:

  • If in a complete pass, no swaps occur, the array is already sorted.
  • This reduces the best-case time complexity to O(n) instead of O(n²).

Optimized Bubble Sort in Java:

static void optimizedBubbleSort(int arr[]) {

    int n = arr.length;

    boolean 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;  // Stop if already sorted

    }

}


This optimization improves performance significantly when the input is partially sorted.

6. Why does Quick Sort have an O(n²) worst-case time complexity?

Quick Sort's worst-case occurs when:

  • The smallest or largest element is always chosen as the pivot.
  • The array is already sorted in ascending or descending order, and no balanced partitioning occurs.
  • This results in T(n) = T(n-1) + O(n) → O(n²) time complexity.


To avoid this, randomized pivot selection or choosing the median pivot is recommended.

7. How does Merge Sort work in a linked list, and why is it better than Quick Sort for linked lists?

Merge Sort is preferred for linked lists because:


  • It does not require random access to elements.
  • It sorts efficiently in O(n log n) time, even without additional space (in recursive implementations).
  • Quick Sort requires frequent swapping, which is expensive in linked lists.

8. Why is Selection Sort not a stable algorithm? Can it be made stable?

Selection Sort is not stable because:

  • It swaps the minimum element with the first unsorted element, which may move an equal-value element before another occurrence of the same value.
  • Example: Sorting [(A, 3), (B, 3), (C, 2)] using Selection Sort can place (B, 3) before (A, 3), changing their original order.


To make it stable, we can modify Selection Sort by using linked lists or keeping track of indexes instead of swapping values directly.

9. Why does Merge Sort require extra space, and how can it be optimized?

Merge Sort requires O(n) extra space because:

  • It uses temporary arrays to merge two halves.
  • Each recursive call needs new storage for merged subarrays.

Optimizations to reduce space:


  • Use in-place Merge Sort, but this makes merging more complex (using extra swaps instead of new arrays).
  • Use Iterative Merge Sort, which reduces recursion stack overhead.

10. Can sorting be done in O(n) time? If yes, how?

Yes, sorting can be done in O(n) time, but only for special cases, such as:

  1. Counting Sort - When the range of numbers is small (O(n+k)).
  2. Radix Sort - If numbers have a limited number of digits (O(d * (n + b)) where b is the base and d is the number of digits).
  3. Bucket Sort - When input data is uniformly distributed (O(n) in best cases).

These non-comparison sorts work by categorizing elements into buckets instead of using comparisons (O(n log n) is the lower bound for comparison-based sorts).


 

Posted on 16 Apr 2025, this text provides information on Algorithms. Please note that while accuracy is prioritized, the data presented might not be entirely correct or up-to-date. This information is offered for general knowledge and informational purposes only, and should not be considered as a substitute for professional advice.

Similar Tutorials


Top 5 Interview Problems in Advanced Data Structur...

Introduction In today's highly competitive tech job market, Data Structures and Algorithms (DSA)...

Shivam Pandey
5 days ago