article

Shell sort is a sorting algorithm that requires asymptotically fewer than O(n²) comparisons and exchanges in the worst case. Although it is easy to develop an intuitive sense of how this algorithm works, it is very difficult to analyze its execution time, but estimates range from O(nlog2 n) to O(n1.5) depending on implementation details.

Shell sort is a generalization of insertion sort, with two observations in mind:

  1. Insertion sort is efficient if the input is "almost sorted".
  2. Insertion sort is inefficient, on average, because it moves values just one position at a time.

Shell sort improves insertion sort by comparing elements separated by a gap of several positions. This lets an element take "bigger steps" toward its expected position. Multiple passes over the data are taken with smaller and smaller gap sizes. The last step of Shell sort is a plain insertion sort, but by then, the array of data is guaranteed to be almost sorted.

Consider a small value that is initially stored in the wrong end of the array. Using an O(n²) sort such as bubble sort or insertion sort, it will take roughly n comparisons and exchanges to move this value all the way to the other end of the array. Shell sort first moves values using giant step sizes, so a small value will move a long way towards its final position, with just a few comparisons and exchanges.

The Shell sort is named after its inventor, Donald Shell, who published it in 1959. Some older textbooks and references incorrectly call this the "Shell-Metzner" sort after Marlene Metzner Norton, but according to Metzner, "I had nothing to do with the sort, and my name should never have been attached to it." *

The Gap sequence


The gap sequence is an integral part of the shellsort algorithm. Any increment sequence will work, so long as the last element is 1. The algorithm begins by performing a gap insertion sort, with the gap being the first number in the gap sequence. It continues to perform a gap insertion sort for each number in the sequence, until it finishes with a gap of 1. When the gap is 1, the gap insertion sort is simply an ordinary insertion sort, guaranteeing that the final list is sorted.

The gap sequence that was originally suggested by Donald Shell was to begin with N/2 and half the number until it reaches 1. While this sequence provides significant performance enhancements over the Quadratic algorithms such as Insertion sort, it can be changed slightly to further decrease the average and worst-case running times.

Perhaps the most crucial property of Shellsort is that the elements remain k-sorted even as the gap diminishes. For instance, if a list was 5-sorted and then 3-sorted, the list is now not only 3-sorted, but both 5- and 3-sorted. If this were not true, the algorithm would undo work that it had done in previous iterations, and would not achieve such a low running time.

Depending on the choice of gap sequence, Shellsort has a worst-case running time of O(n^2), O(n^{3/2}), O(n^{4/3}), or O(n\log^2 n). The existence of an O(n \log n) worst-case implementation of Shellsort remains an open research question.

Example Implementations


Shell sort in C

/* BY BSF * Performs an insertion sort on elements of a* with the given gap. * If gap == 1, performs an ordinary insertion sort. * If gap >= length, does nothing. * Based on a C implementation from the article Insertion sort implementations */ void shellSortPhase(int a*, int length, int gap) { int i; for (i = gap; i < length; ++i) { int value = a*; int j; for (j = i - gap; j >= 0 && a* > value; j -= gap) { a+ gap = a*; } a+ gap = value; } }//end for void shellSort(int a*, size_t length) { /* * gaps* should approximate a geometric progression. * The following sequence is the best known in terms of * the average number of key comparisons made * */ static const int gaps* = { 1, 4, 10, 23, 57, 132, 301, 701 }; int sizeIndex; for (sizeIndex = sizeof(gaps)/sizeof(gaps*) - 1; sizeIndex >= 0; --sizeIndex) shellSortPhase(a, length, gaps*); }

Shell sort in Haskell

import Data.List (transpose) -- Insertion sort, for sorting columns. insert :: Ord a => a -> -> [a insert x = [x insert x (y:ys) | x <= y = x : y:ys | otherwise = y : insert x ys insertionSort :: Ord a => -> [a insertionSort = foldr insert * -- Splits a list into k columns. columnize :: Int -> * -> a columnize k = transpose . takeWhile (not . null) . map (take k) . iterate (drop k) -- Merges columns back into a single list. decolumnize :: a -> * decolumnize = concat . transpose -- Each phase of the Shell sort breaks the list into k columns, sorts each with an -- insertion sort, then merges those columns back into a list. shellSortPhase :: (Ord a) => Int -> -> [a shellSortPhase k = decolumnize . map insertionSort . columnize k -- The full Shell sort, applying phases with arbitrarily large gap sizes according to -- R. Sedgewick, J. Algorithms 7 (1986), 159-173 shellSort :: (Ord a) => -> [a shellSort xs = foldr shellSortPhase xs gaps where gaps = takeWhile (< length xs) sedgewick sedgewick = concat [[9 * 2^n - 9 * 2^(n `div` 2) + 1, 8 * 2^(n+1) - 6 * 2^(n `div` 2) + 1] | n <- *]

Reference


External links


Sort algorithms | Comparison sorts

Shellsort | Ordenación Shell Sort | Tri de Shell | Shell sort | Šelo rūšiavimo algoritmas | Shellsort | シェルソート | Sortowanie Shella | Shell sort | Сортировка методом Шелла | 希尔排序

 

This article is licensed under the GNU Free Documentation License. It uses material from the "Shell sort".

Home Pageartsbusinesscomputersgameshealthhospitalshomekids & teensnewsphysiciansrecreationreferenceregionalscienceshoppingsocietysportsworld