Shell sort using Sedgewick gap sequence for improved practical performance.
Shell sort with Sedgewick gaps uses a carefully designed sequence that improves both theoretical and practical performance over earlier sequences such as Shell and Hibbard.
Two common Sedgewick sequences are used in practice. A widely cited version is:
This produces gaps such as:
You use all values less than , in decreasing order.
Problem
Given a sequence of length , reorder it such that
Gap Sequence
Generate all Sedgewick gaps less than , then apply them in descending order.
Example for :
Algorithm
For each gap, perform insertion sort on elements spaced by that gap.
shell_sort_sedgewick(A):
n = length(A)
gaps = generate_sedgewick_gaps(n)
for gap in reverse(gaps):
for i from gap to n - 1:
key = A[i]
j = i
while j >= gap and A[j - gap] > key:
A[j] = A[j - gap]
j = j - gap
A[j] = keyExample
Let
For , Sedgewick gaps are:
Gap 5:
→ reduces long-distance inversions
Gap 1:
→ final insertion sort
Result:
Correctness
Each gap enforces ordering among elements spaced by that gap. As gaps decrease, the array becomes increasingly structured. The final pass with gap 1 ensures full sorting.
Complexity
| case | time |
|---|---|
| worst | about |
| average | close to |
| best |
Space complexity:
Properties
- in-place
- not stable
- strong practical performance
- widely used in tuned Shell sort implementations
When to Use
Sedgewick gaps are preferred when using Shell sort in practice. They offer a good balance between simplicity and performance without requiring complex tuning.
Implementation
def sedgewick_gaps(n):
gaps = []
k = 0
while True:
if k % 2 == 0:
gap = 9 * (2**k) - 9 * (2**(k//2)) + 1
else:
gap = 8 * (2**k) - 6 * (2**((k+1)//2)) + 1
if gap >= n:
break
gaps.append(gap)
k += 1
return gaps
def shell_sort_sedgewick(a):
n = len(a)
gaps = sedgewick_gaps(n)
for gap in reversed(gaps):
for i in range(gap, n):
key = a[i]
j = i
while j >= gap and a[j - gap] > key:
a[j] = a[j - gap]
j -= gap
a[j] = key
return afunc SedgewickGaps(n int) []int {
gaps := []int{}
for k := 0; ; k++ {
var gap int
if k%2 == 0 {
gap = 9*(1<<k) - 9*(1<<(k/2)) + 1
} else {
gap = 8*(1<<k) - 6*(1<<((k+1)/2)) + 1
}
if gap >= n {
break
}
gaps = append(gaps, gap)
}
return gaps
}
func ShellSortSedgewick[T constraints.Ordered](a []T) {
gaps := SedgewickGaps(len(a))
for g := len(gaps) - 1; g >= 0; g-- {
gap := gaps[g]
for i := gap; i < len(a); i++ {
key := a[i]
j := i
for j >= gap && a[j-gap] > key {
a[j] = a[j-gap]
j -= gap
}
a[j] = key
}
}
}