Shell sort using Hibbard gap sequence 1, 3, 7, 15, ..., improving over simple halving.
Shell sort with Hibbard gaps replaces the simple halving sequence with a more structured progression:
This sequence produces gaps such as:
In practice, you use the largest value less than , then proceed in decreasing order down to 1.
This improves performance over the basic Shell gap sequence by reducing long-distance disorder more effectively.
Problem
Given a sequence of length , reorder it such that
Gap Sequence
Construct all values of the form:
Sort them in descending order and use them as gaps.
Example for :
Algorithm
For each gap, perform insertion sort over elements spaced by that gap.
shell_sort_hibbard(A):
n = length(A)
gaps = []
k = 1
while (2^k - 1) < n:
gaps.append(2^k - 1)
k = k + 1
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 , Hibbard gaps are:
Gap 7:
→ compare elements far apart
Gap 3:
→ reduce disorder further
Gap 1:
→ final insertion sort
Result:
Correctness
Each gap sorts subsequences formed by stepping through the array with stride . As gaps decrease, elements move closer to their correct positions. The final gap of 1 ensures a fully sorted sequence.
Complexity
| case | time |
|---|---|
| worst | |
| average | about |
| best |
Space complexity:
Properties
- in-place
- not stable
- better theoretical bounds than simple gaps
When to Use
Hibbard gaps provide a good balance between simplicity and performance. They are suitable when you want a predictable improvement over naive Shell sort without complex tuning.
Implementation
def shell_sort_hibbard(a):
n = len(a)
gaps = []
k = 1
while (2**k - 1) < n:
gaps.append(2**k - 1)
k += 1
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 ShellSortHibbard[T constraints.Ordered](a []T) {
n := len(a)
var gaps []int
for k := 1; (1<<k)-1 < n; k++ {
gaps = append(gaps, (1<<k)-1)
}
for g := len(gaps) - 1; g >= 0; g-- {
gap := gaps[g]
for i := gap; i < n; i++ {
key := a[i]
j := i
for j >= gap && a[j-gap] > key {
a[j] = a[j-gap]
j -= gap
}
a[j] = key
}
}
}