AlgoPlusAlgoPlus
Learn/Data Structures & Algorithms
Lesson

Shell Sort

Insertion sort with a head start: sort items a large gap apart first, then shrink the gap to 1.

8 min read Watch it move Build it

Shell sort is insertion sort with a head start. Plain insertion sort moves items only one step at a time, which is agony when a small value sits far from home. Shell sort fixes that by first comparing items a large gap apart — a single hop can move a stray value most of the way home — then repeating with smaller and smaller gaps until the gap is 1.

Gapped insertion sort

For a given gap g, you run an ordinary insertion sort but on elements spaced g apart instead of adjacent ones — this is gapped insertion. Large early gaps shove out-of-place values across long distances cheaply. By the time the gap shrinks to 1 (an ordinary insertion sort), the array is already nearly sorted, so that final pass barely has to move anything.

  1. 1Pick a gap sequence that starts large and shrinks to 1 (e.g. n/2, n/4, …, 1).
  2. 2For each gap g, run insertion sort comparing elements g apart.
  3. 3Each value slides back over g-spaced larger values into its gapped slot.
  4. 4Shrink the gap and repeat; the gap-1 pass finishes an almost-sorted array fast.
function shellSort(arr) {
  const n = arr.length;
  for (let gap = n >> 1; gap > 0; gap >>= 1) {  // shrinking gaps
    for (let i = gap; i < n; i++) {
      const key = arr[i];
      let j = i;
      while (j >= gap && arr[j - gap] > key) {  // gapped insertion
        arr[j] = arr[j - gap];
        j -= gap;
      }
      arr[j] = key;
    }
  }
  return arr;
}
The gap sequence is everything
Shell sort's speed depends entirely on the chosen sequence of gaps. The naive n/2 halving gives roughly O(n²) worst case, but better sequences (Hibbard, Sedgewick, Knuth's 3k+1) push the typical cost down to around O(n^1.3) — a big win over plain insertion sort, with no extra memory.
Long hops break stability
Because a gapped move can jump a value across many positions, equal values can be reordered — shell sort is unstable, unlike the plain insertion sort it's built from.
OperationTimeSpace
Typical · depends on the gap sequence~O(n^1.3)O(1)
Worst · poor gap sequenceO(n²)O(1)
Check yourself
What does using large gaps first buy shell sort over plain insertion sort?