Insertion Sort
Build a sorted array one element at a time by inserting each into its correct position.
The Mathematics
Loop invariant, stability, and case analysis
Loop Invariant
At the start of each outer loop iteration , the subarray consists of the elements originally in but in sorted order:
Each iteration takes element (the key) and inserts it into the correct position within the sorted prefix, extending the sorted region by one.
Complexity Analysis
The number of comparisons depends on the input order:
Each key is already in place — inner loop never executes.
Each key shifts all the way to position 0: .
Expected comparisons: .
Properties
Insertion sort has several useful properties:
Stable: equal elements maintain their relative order (compare with , not )
In-place: uses only extra space
Adaptive: runs in where is the number of inversions
Online: can sort elements as they arrive
When to Use Insertion Sort
Optimal for small arrays () or nearly-sorted data. Many hybrid algorithms (Timsort, introsort) use insertion sort as a subroutine for small partitions.
See It Work
Sorting [5, 2, 8, 1, 9, 3] by inserting each element into the sorted prefix
Initialize: first element [5] is trivially sorted. Start from index 1.
The Code
Bridge from loop invariant to Python implementation
Mathematical Formulation
Outer loop extends the sorted region one element at a time
Save the current element to insert into the sorted prefix
Inner loop finds where key belongs by scanning right to left
Shift larger elements one position to the right
Place the key at its correct sorted position
Loop invariant: after each outer iteration, A[0..i] is sorted
Python Implementation
def insertion_sort(A):
n = len(A)
for i in range(1, n): # Outer: extend sorted region
key = A[i] # Element to insert
j = i - 1
while j >= 0 and A[j] > key: # Inner: find insertion point
A[j + 1] = A[j] # Shift element right
A[j + 1] = key # Insert key at correct position
return A