Skip to content

Insertion Sort

Definition

A comparison-based sorting algorithm that builds the sorted array one element at a time by inserting each element into its correct position in the sorted portion. Like sorting playing cards in your hand!

Insertion Sort Visualization


Big O Complexity

Insertion Sort Time and Space Complexity


When to Use

When to Use Insertion Sort


Pros and Cons

Insertion Sort Pros and Cons


Implementation

Basic Insertion Sort

public void insertionSort(int[] arr) {
    int n = arr.length;

    for (int i = 1; i < n; i++) {
        int key = arr[i];  // Element to insert
        int j = i - 1;

        // Shift elements greater than key to the right
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }

        // Insert key at correct position
        arr[j + 1] = key;
    }
}

With Swaps (Less Efficient)

public void insertionSortSwap(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        for (int j = i; j > 0 && arr[j] < arr[j - 1]; j--) {
            // Swap
            int temp = arr[j];
            arr[j] = arr[j - 1];
            arr[j - 1] = temp;
        }
    }
}

Binary Insertion Sort

// Use binary search to find insertion point
// Reduces comparisons from O(n²) to O(n log n)
// But still O(n²) shifts
public void binaryInsertionSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        int key = arr[i];

        // Binary search for insertion position
        int insertPos = binarySearch(arr, 0, i - 1, key);

        // Shift elements right
        for (int j = i - 1; j >= insertPos; j--) {
            arr[j + 1] = arr[j];
        }
        arr[insertPos] = key;
    }
}

private int binarySearch(int[] arr, int low, int high, int key) {
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (arr[mid] == key) return mid + 1;
        if (arr[mid] < key) low = mid + 1;
        else high = mid - 1;
    }
    return low;
}

Recursive Insertion Sort

public void insertionSortRecursive(int[] arr, int n) {
    if (n <= 1) return;

    // Sort first n-1 elements
    insertionSortRecursive(arr, n - 1);

    // Insert nth element into sorted portion
    int key = arr[n - 1];
    int j = n - 2;

    while (j >= 0 && arr[j] > key) {
        arr[j + 1] = arr[j];
        j--;
    }
    arr[j + 1] = key;
}

Descending Order

public void insertionSortDescending(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        int key = arr[i];
        int j = i - 1;

        while (j >= 0 && arr[j] < key) {  // Changed comparison
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

Generic Insertion Sort

public <T extends Comparable<T>> void insertionSort(T[] arr) {
    for (int i = 1; i < arr.length; i++) {
        T key = arr[i];
        int j = i - 1;

        while (j >= 0 && arr[j].compareTo(key) > 0) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

Step-by-Step Example

Insertion Sort Step-by-Step Example


Variations

Insertion Sort for Linked List

public ListNode insertionSortList(ListNode head) {
    if (head == null) return null;

    ListNode dummy = new ListNode(0);  // Sorted list
    ListNode curr = head;

    while (curr != null) {
        ListNode next = curr.next;

        // Find insertion position in sorted list
        ListNode prev = dummy;
        while (prev.next != null && prev.next.val < curr.val) {
            prev = prev.next;
        }

        // Insert curr after prev
        curr.next = prev.next;
        prev.next = curr;

        curr = next;
    }

    return dummy.next;
}

Shell Sort (Generalization of Insertion Sort)

// Uses gaps to reduce number of shifts
public void shellSort(int[] arr) {
    int n = arr.length;

    // Start with large gap, reduce to 1
    for (int gap = n / 2; gap > 0; gap /= 2) {
        // Perform insertion sort for this gap
        for (int i = gap; i < n; i++) {
            int key = arr[i];
            int j = i;

            while (j >= gap && arr[j - gap] > key) {
                arr[j] = arr[j - gap];
                j -= gap;
            }
            arr[j] = key;
        }
    }
}

Insertion Sort for Partially Sorted

// When only k elements are out of place
// Time: O(n × k)
public void insertionSortPartial(int[] arr) {
    // Same as basic insertion sort
    // Naturally efficient for nearly sorted arrays
    insertionSort(arr);
}

Use in Hybrid Sorts

Insertion Sort in Hybrid Algorithms

Hybrid Quick Sort Example

public void hybridSort(int[] arr, int low, int high) {
    while (low < high) {
        // Use insertion sort for small arrays
        if (high - low < 10) {
            insertionSort(arr, low, high);
            break;
        }

        // Otherwise use quicksort partition
        int pivot = partition(arr, low, high);

        // Recurse on smaller partition, iterate on larger
        if (pivot - low < high - pivot) {
            hybridSort(arr, low, pivot - 1);
            low = pivot + 1;
        } else {
            hybridSort(arr, pivot + 1, high);
            high = pivot - 1;
        }
    }
}

private void insertionSort(int[] arr, int low, int high) {
    for (int i = low + 1; i <= high; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= low && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

Tips & Tricks

Insertion Sort Tips and Tricks