← Back to Data Structures & Algorithms

Elementary sorts

Sorting arranges items in order and underlies searching, merging, de-duplication, and countless other tasks. Simple quadratic sorts are slow on big inputs but teach key ideas and still have practical niches.

Sorting vocabulary

A sorting algorithm rearranges items by a key into non-decreasing order. Important properties: time complexity in the best, average, and worst cases; space, especially whether it sorts in place with O(1) extra memory; stability, whether equal keys keep their original relative order; and adaptivity, whether it runs faster on nearly sorted input.

Bubble sort

Bubble sort repeatedly passes through the list, swapping adjacent items that are out of order, so large items 'bubble' to the end. After pass k, the last k items are in place. It takes O(n^2) comparisons in the worst and average cases; with an early-exit check when a pass makes no swaps, it takes O(n) on already sorted data. It is stable and in place but rarely used in practice.

Selection sort

Selection sort finds the smallest remaining item and swaps it into the next position, repeating n - 1 times. It always makes about n^2 / 2 comparisons, regardless of input, but only n - 1 swaps, which can matter when writes are expensive. The standard version is not stable, because long-distance swaps can jump an item past an equal one.

Insertion sort

Insertion sort grows a sorted prefix: each new item is shifted left past larger items until it fits. Worst case O(n^2), for reverse-sorted input, but O(n) for sorted input and fast whenever items are close to their final positions. Its cost is O(n + I), where I is the number of inversions, pairs out of order. It is stable, in place, and simple.

Why insertion sort still matters

On small arrays, around 10 to 30 items, insertion sort's low overhead beats more sophisticated algorithms. So practical sorts, including Timsort and introsort, switch to insertion sort for small pieces. It also suits data that arrives nearly sorted, such as a list with a few new entries appended.

Shellsort

Shellsort, by Donald Shell in 1959, runs insertion sort on items a gap apart, then shrinks the gap, finishing with a gap of 1. Early passes move items long distances cheaply, so the final insertion sort has little left to do. With good gap sequences it runs in roughly O(n^(4/3)) or better in practice, with no extra memory, though its exact complexity depends on the gaps.

Inversions

An inversion is a pair of positions i < j with a[i] > a[j]. A sorted array has 0; a reversed array of n items has n(n - 1)/2, the maximum. Swapping adjacent items removes exactly one inversion, which proves that any algorithm sorting only by adjacent swaps, such as bubble and insertion sort, needs on the order of n^2 swaps on average.

Worked example

Insertion sort on [5, 2, 4, 1]: insert 2: shift 5, giving [2, 5, 4, 1]. Insert 4: shift 5, giving [2, 4, 5, 1]. Insert 1: shift 5, 4, and 2, giving [1, 2, 4, 5]. Total shifts: 1 + 1 + 3 = 5, which equals the original number of inversions: (5,2), (5,4), (5,1), (2,1), (4,1).

Key takeaways

Sorting algorithms are judged by time, space, stability, and adaptivity. Bubble sort swaps neighbours, O(n^2), with an O(n) early exit on sorted data. Selection sort always does about n^2 / 2 comparisons but only n - 1 swaps and is unstable. Insertion sort is stable, adaptive, O(n + inversions), and best for small or nearly sorted arrays, which is why hybrid sorts use it. Shellsort sorts gapped subsequences for sub-quadratic performance. Adjacent-swap sorts need about n^2 / 4 swaps on average, because each swap fixes one inversion.

Flashcard

Stable sort

Equal keys keep their relative order

Important for multi-key sorts.

Check your understanding

Which elementary sort runs in close to linear time on an array that is already almost sorted?

← Previous lesson Next lesson →