Insertion Sort Big O Analysis- Time Complexity Explained

What Is Insertion Sort and Why Should You Care About Its Big O?

Insertion sort is one of those algorithms you probably use every day without realizing it. When you sort a deck of cards in your hand, you're doing insertion sort. You pick up a card, compare it to others, and slide it into the right position. That's the whole algorithm.

Here's the thing: insertion sort isn't fast. Not by a long shot. But it has specific scenarios where it shines, and understanding when to use it separates junior developers from experienced ones.

The Time Complexity Breakdown

Let's get straight to the numbers. Insertion sort's time complexity depends entirely on the state of your input data.

Best Case: O(n)

When your array is already sorted, insertion sort runs in linear time. It still walks through each element once, but never needs to shift anything.

You check if each element is greater than the previous one. If yes, move on. That's it.

Average Case: O(n²)

This is where insertion sort hurts. For a randomly shuffled array, roughly half the elements need to be moved on average. That gives you quadratic time.

For 1,000 elements, you're looking at around 500,000 comparisons. For 10,000 elements, that jumps to roughly 50 million. The growth is brutal.

Worst Case: O(n²)

When your array is reverse sorted, every new element gets compared with every element before it. You shift almost everything each time.

This is insertion sort at its absolute worst. A reverse-sorted array of 5,000 elements will take noticeably long to sort.

Space Complexity: The One Bright Spot

Insertion sort uses O(1) auxiliary space. It sorts in-place. You don't need a secondary array. You don't need recursion. You just need the original array and a single variable for the element being inserted.

This is why insertion sort still shows up in practice despite its slow average-case performance.

When Insertion Sort Actually Makes Sense

Most developers will tell you to never use insertion sort. They're wrong. Insertion sort is the right choice in these specific situations:

Comparison With Other Sorting Algorithms

Here's how insertion sort stacks up against the competition:

Algorithm Best Case Average Case Worst Case Space
Insertion Sort O(n) O(n²) O(n²) O(1)
Bubble Sort O(n) O(n²) O(n²) O(1)
Selection Sort O(n²) O(n²) O(n²) O(1)
Merge Sort O(n log n) O(n log n) O(n log n) O(n)
Quick Sort O(n log n) O(n log n) O(n²) O(log n)

Notice that bubble sort and selection sort have the same asymptotic complexity as insertion sort. But insertion sort is faster in practice because it does fewer comparisons on average and has better cache locality.

How To Implement Insertion Sort

Here's a working implementation in Python. No frills, no object-oriented wrappers. Just the algorithm:

def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        
        while j >= 0 and arr[j] > key:
            arr[j + 1] = arr[j]
            j -= 1
        
        arr[j + 1] = key
    
    return arr

And here's the same thing in JavaScript:

function insertionSort(arr) {
    for (let i = 1; i < arr.length; i++) {
        const key = arr[i];
        let j = i - 1;
        
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        
        arr[j + 1] = key;
    }
    
    return arr;
}

The logic is dead simple. For each element starting at index 1, shift larger elements one position right until you find the right spot for the current element. Insert it there.

Why Cache Locality Matters More Than Big O

Here's something textbooks rarely mention: insertion sort has excellent cache performance. When you access arr[j] and then arr[j+1], those elements are right next to each other in memory. Modern CPUs cache this data, making the operations blazingly fast.

Quick sort, despite its O(n log n) theoretical advantage, suffers from cache misses when it accesses elements far apart in memory during partitioning. For arrays that fit in CPU cache, insertion sort often runs faster than quicksort for small inputs.

This is why many programming languages use insertion sort as the final stage of their hybrid sorting algorithms. Python's Timsort, Java's Dual-Pivot Quicksort, and GNU's sort all switch to insertion sort for small subarrays.

The Bottom Line

Insertion sort's Big O is O(n²) for average and worst cases. That's slow, and you shouldn't use it for large datasets.

But its O(n) best case, O(1) space usage, and superior cache performance make it the right tool for nearly sorted data, small arrays, and online sorting scenarios.

Know your data. Know your algorithm. The choice is rarely about what's theoretically "best" — it's about what works best for your specific situation.