Shell Sort
Description
Shell Sort is an optimization of insertion sort that allows the exchange of items that are far apart. The algorithm is named after its inventor, Donald Shell, who published it in 1959. Instead of comparing only adjacent elements, Shell Sort starts by comparing elements that are far apart and progressively reduces the gap between elements being compared.
History

Shell Sort was invented by Donald L. Shell and published in 1959 in the journal Communications of the ACM. At the time, Shell was working at General Electric and developed this algorithm as a solution to improve the efficiency of insertion sort. The algorithm was groundbreaking because it was the first sorting algorithm to achieve sub-quadratic time complexity. Before Shell Sort, the best-known general-purpose sorting algorithms all had O(n²) time complexity. Shell's innovation was to allow the exchange of elements that are far apart, which helps to move items into their correct position faster than a simple adjacent exchange would. The original gap sequence proposed by Shell was n/2, but since then, many researchers have proposed and analyzed different gap sequences. Some notable sequences include Knuth's sequence (3ᵏ - 1) and Ciura's sequence (1, 4, 10, 23, 57, 132, 301, 701).
How It Works
- Gap Selection: Start with a large gap and reduce it over iterations
- Initially gap = N/2
- Each iteration: gap = gap/2
- Gapped Insertion Sort:
- Compare elements that are gap positions apart
- Swap them if they are in wrong order
- Continue until gap becomes 1
- Final Pass: When gap = 1, perform regular insertion sort
Visualization
Click Start to begin visualization
Implementation
def shell_sort(arr):
n = len(arr)
gap = n // 2
while gap > 0:
for i in range(gap, n):
temp = arr[i]
j = i
# Shift elements that are gap positions apart
while j >= gap and arr[j - gap] > temp:
arr[j] = arr[j - gap]
j -= gap
arr[j] = temp
gap //= 2
return arr
# Example usage
if __name__ == "__main__":
arr = [64, 34, 25, 12, 22, 11, 90]
print("Original array:", arr)
sorted_arr = shell_sort(arr)
print("Sorted array:", sorted_arr)
void shellSort(vector& arr) {
int n = arr.size();
// Start with a big gap, then reduce the gap
for (int gap = n/2; gap > 0; gap /= 2) {
// Do a gapped insertion sort for this gap size
for (int i = gap; i < n; i++) {
// Add arr[i] to the elements that have been gap sorted
int temp = arr[i];
int j;
// Shift earlier gap-sorted elements up until the correct location for arr[i] is found
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
arr[j] = arr[j - gap];
}
// Put temp (the original arr[i]) in its correct location
arr[j] = temp;
}
}
}
// Example usage
int main() {
vector arr = {64, 34, 25, 12, 22, 11, 90};
cout << "Original array: ";
for(int num : arr) cout << num << " ";
shellSort(arr);
cout << "\nSorted array: ";
for(int num : arr) cout << num << " ";
return 0;
}
public class ShellSort
{
public static void Sort(int[] arr)
{
int n = arr.Length;
// Start with a big gap, then reduce the gap
for (int gap = n/2; gap > 0; gap /= 2)
{
// Do a gapped insertion sort for this gap size
for (int i = gap; i < n; i++)
{
// Add arr[i] to the elements that have been gap sorted
int temp = arr[i];
int j;
// Shift earlier gap-sorted elements up until the correct
// location for arr[i] is found
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap)
{
arr[j] = arr[j - gap];
}
// Put temp (the original arr[i]) in its correct location
arr[j] = temp;
}
}
}
// Example usage
public static void Main(string[] args)
{
int[] arr = { 64, 34, 25, 12, 22, 11, 90 };
Console.WriteLine("Original array: " + string.Join(" ", arr));
Sort(arr);
Console.WriteLine("Sorted array: " + string.Join(" ", arr));
}
}
Gap Sequences
Different gap sequences can lead to different time complexities:
Sequence Name | Sequence | Time Complexity |
---|---|---|
Shell's Original | N/2, N/4, ..., 1 | O(n²) |
Knuth's | 1, 4, 13, 40, ... | O(n^(3/2)) |
Ciura's | 1, 4, 10, 23, 57, ... | Unknown (Best empirical) |
Advantages and Disadvantages
Advantages
- In-place algorithm
- Adaptive algorithm
- Better than simple insertion sort
- Works well for medium-sized arrays
Disadvantages
- Not stable
- Complex gap sequence selection
- Performance depends on gap sequence
- Not as efficient as quick sort or merge sort