Back

Time Complexity of Sorting Algorithms

Last Updated: March 18, 2025
5 min
Time Complexity of Sorting Algorithms

Table of Content

Introduction: When My Grocery List Turned Into a Sorting Nightmare

Imagine this: You’re trying to sort your music playlist by song length, but your app freezes. “Why is this taking so long?!” you groan. The answer? Sorting algorithms—the unsung heroes (or villains) of your coding life. Let’s unravel their time and space complexities, sprinkle in some humor, and learn which algorithm to use so your next project doesn’t crash like a toddler’s block tower.


What’s Time Complexity?

Time complexity predicts how fast an algorithm runs as data grows. It’s like guessing how long it’ll take to find a matching sock:

  • Best-case: Books are pre-sorted (O(1)).
  • Average-case: Books are scattered (O(n log n)).
  • Worst-case: Books are in another dimension (O(n²)).

Big O Notation simplifies this by focusing on growth trends. For example, 4n² + 3n becomes O(n²).

Space Complexity tracks memory usage. Think of it as asking, “How much trunk space do I need?”


Time Complexity of Sorting Algorithms Cheat Sheet

Here’s a quick reference for time and space complexity:

Algorithm Best Time Average Time Worst Time Worst Space
Bubble Sort O(n) O(n²) O(n²) O(1)
Selection Sort O(n²) O(n²) O(n²) O(1)
Insertion Sort O(n) O(n²) O(n²) O(1)
Heap Sort O(n log n) O(n log n) O(n log n) O(1)
Quick Sort O(n log n) O(n log n) O(n²) O(n)
Merge Sort O(n log n) O(n log n) O(n log n) O(n)
Bucket Sort O(n + k) O(n + k) O(n²) O(n)
Radix Sort O(nk) O(nk) O(nk) O(n + k)
Count Sort O(n + k) O(n + k) O(n + k) O(k)
Shell Sort O(n log n) O(n log n) O(n²) O(1)
Tim Sort O(n) O(n log n) O(n log n) O(n)
Tree Sort O(n log n) O(n log n) O(n²) O(n)
Cube Sort O(n) O(n log n) O(n log n) O(n)

Translation:

  • O(n²): “Time to binge a show while waiting.”
  • O(n log n): “Efficient and reliable.”
  • O(n): “Blink and you’ll miss it.”

Comparison Based Sorting Algorithms

These algorithms compare elements to decide their order.

1. Bubble Sort: Time Complexity of Bubble Sort

Definition: Repeatedly swaps adjacent elements like overly chatty neighbors until the list is sorted.

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n-1; i++) {  
        bool swapped = false;  
        for (int j = 0; j < n-i-1; j++) {  
            if (arr[j] > arr[j+1]) {  
                swap(arr[j], arr[j+1]);  
                swapped = true;  
            }  
        }  
        if (!swapped) break; // Exit early if sorted  
    }  
}  

Time Complexity: O(n²) average/worst, O(n) best (if already sorted).

When to Use: Tiny datasets or teaching recursion. Like using a spoon to dig a pool.

Real-World Use: Teaching recursion, or sorting your DVD collection (if you still have one).


2. Selection Sort: Time Complexity of Selection Sort

Definition: Finds the smallest element and swaps it to the front, repeating until sorted. Like picking the shortest checkout line—only for a new one to open immediately. How It Feels: Like choosing the shortest grocery line, only for a new line to open immediately.

void selectionSort(int arr[], int n) {
    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;  
        }  
        swap(arr[minIndex], arr[i]);  
    }  
}  

Time Complexity: O(n²) for all cases. Space: O(1).

When to Use: Almost never. It’s the “participation trophy” of sorting.

Real-World Use: Never. Seriously, use Insertion Sort instead.


3. Insertion Sort: Time Complexity of Insertion Sort

Definition: Builds the sorted array one element at a time, like sorting a hand of cards.

void insertionSort(int arr[], int n) {
    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;  
    }  
}  

Time Complexity: O(n²) average/worst, O(n) best.

When to Use: Small or nearly sorted data. Think alphabetizing your spice rack.

Real-World Use: Small datasets, like arranging spices alphabetically.


4. Quick Sort: Time Complexity of Quick Sort

Definition: Picks a pivot, partitions the array around it, then recursively sorts each half. How It Works: Picks a pivot, partitions the array, and recursively sorts each half.

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++;  
            swap(arr[i], arr[j]);  
        }  
    }  
    swap(arr[i+1], arr[high]);  
    return i + 1;  
}  
 
void quickSort(int arr[], int low, int high) {  
    if (low < high) {  
        int pi = partition(arr, low, high);  
        quickSort(arr, low, pi - 1);  
        quickSort(arr, pi + 1, high);  
    }  
}  

Optimization Tip: Use a random pivot to avoid worst-case scenarios (like sorting a reversed list).

Real-World Use: Default in programming languages like Python and Java.


5. Merge Sort: Time Complexity of Merge Sort

Definition: Splits the array into halves, sorts each, then merges them like zipping two sorted lists.

void merge(int arr[], int l, int m, int r) {
    // ... (see previous example)  
}  
 
void mergeSort(int arr[], int l, int r) {  
    if (l < r) {  
        int m = l + (r - l)/2;  
        mergeSort(arr, l, m);  
        mergeSort(arr, m+1, r);  
        merge(arr, l, m, r);  
    }  
}  

Time Complexity: O(n log n) for all cases.

Real-World Use: Databases, stable sorting (e.g., sorting by date then priority).


6. Heap Sort: Time Complexity of Heap Sort

Definition: Converts the array into a heap data structure, then repeatedly extracts the maximum element.

void heapify(int arr[], int n, int i) {
    int largest = i;  
    int left = 2 * i + 1;  
    int right = 2 * i + 2;  
 
    if (left < n && arr[left] > arr[largest]) largest = left;  
    if (right < n && arr[right] > arr[largest]) largest = right;  
 
    if (largest != i) {  
        swap(arr[i], arr[largest]);  
        heapify(arr, n, largest);  
    }  
}  
 
void heapSort(int arr[], int n) {  
    for (int i = n/2 - 1; i >= 0; i--)  
        heapify(arr, n, i);  
 
    for (int i = n-1; i > 0; i--) {  
        swap(arr[0], arr[i]);  
        heapify(arr, i, 0);  
    }  
}  

Time Complexity: O(n log n) for all cases.

Real-World Use: Memory-constrained systems (since it’s in-place).


Non Comparison Based Sorting Algorithms

These algorithms use data properties (like integer ranges) to sort faster than O(n log n).

1. Bucket Sort: The “Group Project” Strategy

Definition: Splits data into buckets, sorts each bucket, then merges them.

Example: Sorting exam scores (0-100) into grade ranges.

Time Complexity: O(n + k) if data is uniformly distributed.


2. Radix Sort: Time Complexity of Radix Sort

Definition: Sorts numbers digit by digit, like organizing files by year, month, then day.

void countingSortForRadix(int arr[], int n, int exp) {
    int output[n];  
    int count[10] = {0};  
 
    for (int i = 0; i < n; i++)  
        count[(arr[i]/exp) % 10]++;  
 
    for (int i = 1; i < 10; i++)  
        count[i] += count[i-1];  
 
    for (int i = n-1; i >= 0; i--) {  
        output[count[(arr[i]/exp) % 10] - 1] = arr[i];  
        count[(arr[i]/exp) % 10]--;  
    }  
 
    for (int i = 0; i < n; i++)  
        arr[i] = output[i];  
}  
 
void radixSort(int arr[], int n) {  
    int maxVal = *max_element(arr, arr + n);  
    for (int exp = 1; maxVal/exp > 0; exp *= 10)  
        countingSortForRadix(arr, n, exp);  
}  

Time Complexity: O(nk) for all cases.

When to Use: Sorting phone numbers or ZIP codes.

Real-World Use: Sorting phone numbers or ZIP codes.


3. Count Sort: Time Complexity of Count Sort

Definition: Counts occurrences of each element, then rebuilds the sorted array.

Time Complexity: O(n + k), where k is the range of input.

When to Use: Small integer ranges (e.g., ages 0-150).


4. Tree Sort: Time Complexity of Tree Sort

Definition: Inserts elements into a binary search tree, then traverses it in-order.

Time Complexity: O(n log n) best/average, O(n²) worst.

Catch: If the tree becomes unbalanced (like a lopsided bookshelf), performance drops to O(n²).


Key Takeaways

  1. Small data? Use Insertion Sort.
  2. General-purpose? Quick Sort (with a good pivot or avoid worst-case pivots).
  3. Stability matters? Merge Sort.
  4. Non-integers? Bucket/Radix Sort (if data allows). Otherwise, stick to comparison sorts.

Conclusion

Sort Smarter, Not Harder, Code Happily

Sorting algorithms are like kitchen gadgets: use the wrong one, and you’ll end up with a mess like a butter knife works on steak, but you’ll regret it. Now that you’ve got the cheat sheet, go optimize your code—and maybe finally sort that playlist!

P.S. If you catch someone using Bubble Sort for a million elements, offer them a coffee…, and gently suggest this article. Or buy them a stress ball. 😉


Ads