0% found this document useful (0 votes)
12 views

Shellsort

Shellsort is an extension of insertion sort that allows exchanges of array entries that are far apart. It works by h-sorting the array, where h refers to taking every hth entry to form a sorted subsequence. Larger values of h move items long distances, making it easier to h-sort with smaller values of h. Shellsort uses a sequence of h values ending in 1 to fully sort the array. It performs this in place and is faster than insertion and selection sorts, especially for large arrays.

Uploaded by

u17814
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

Shellsort

Shellsort is an extension of insertion sort that allows exchanges of array entries that are far apart. It works by h-sorting the array, where h refers to taking every hth entry to form a sorted subsequence. Larger values of h move items long distances, making it easier to h-sort with smaller values of h. Shellsort uses a sequence of h values ending in 1 to fully sort the array. It performs this in place and is faster than insertion and selection sorts, especially for large arrays.

Uploaded by

u17814
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

258 CHAPTER 2 ■ Sorting

Shellsort To exhibit the value of knowing properties of elementary sorts, we next


consider a fast algorithm based on insertion sort. Insertion sort is slow for large un-
ordered arrays because the only exchanges it does involve adjacent entries, so items
can move through the array only one place at a time. For example, if the item with the
smallest key happens to be at the end of the array, N!1 exchanges are needed to get that
one item where it belongs. Shellsort is a simple extension of insertion sort that gains
speed by allowing exchanges of array entries that are far apart, to produce partially
sorted arrays that can be efficiently sorted, eventually by insertion sort.
The idea is to rearrange the array to give it the property that taking every hth entry
(starting anywhere) yields a sorted subsequence. Such an array is said to be h-sorted. Put
another way, an h-sorted array is h inde-
h=4
pendent sorted subsequences, interleaved
L E E A M H L E P S O L T S X R
L M P T
together. By h-sorting for some large val-
E H S S ues of h, we can move items in the array
E L O X long distances and thus make it easier to
A E L R h-sort for smaller values of h. Using such
a procedure for any sequence of values of
An h-sorted sequence is h interleaved sorted subsequences
h that ends in 1 will produce a sorted ar-
ray: that is shellsort. The implementation
in Algorithm 2.3 on the facing page uses the sequence of decreasing values ½(3k!1),
starting at the largest increment less than N/3 and decreasing to 1. We refer to such a
sequence as an increment sequence. Algorithm 2.3 computes its increment sequence;
another alternative is to store an increment sequence in an array.
One way to implement shellsort would be, for each h, to use insertion sort indepen-
dently on each of the h subsequences. Because the subsequences are independent, we
can use an even simpler approach: when h-sorting the array, we insert each item among
the previous items in its h-subsequence by exchanging it with those that have larger
keys (moving them each one position to the right in the subsequence). We accomplish
this task by using the insertion-sort code, but modified to decrement by h instead of 1
when moving through the array. This observation reduces the shellsort implementa-
tion to an insertion-sort-like pass through the array for each increment.
Shellsort gains efficiency by making a tradeoff between size and partial order in the
subsequences. At the beginning, the subsequences are short; later in the sort, the subse-
quences are partially sorted. In both cases, insertion sort is the method of choice. The
extent to which the subsequences are partially sorted is a variable factor that depends
strongly on the increment sequence. Understanding shellsort’s performance is a chal-
lenge. Indeed, Algorithm 2.3 is the only sorting method we consider whose perfor-
mance on randomly ordered arrays has not been precisely characterized.
2.1 ■ Elementary Sorts 259

ALGORITHM 2.3 Shellsort

public class Shell


{
public static void sort(Comparable[] a)
{ // Sort a[] into increasing order.
int N = a.length;
int h = 1;
while (h < N/3) h = 3*h + 1; // 1, 4, 13, 40, 121, 364, 1093, ...
while (h >= 1)
{ // h-sort the array.
for (int i = h; i < N; i++)
{ // Insert a[i] among a[i-h], a[i-2*h], a[i-3*h]... .
for (int j = i; j >= h && less(a[j], a[j-h]); j -= h)
exch(a, j, j-h);
}
h = h/3;
}
}
// See page 245 for less(), exch(), isSorted(), and main().
}

If we modify insertion sort (Algorithm 2.2) to h-sort the array and add an outer loop to decrease
h through a sequence of increments starting at an increment as large as a constant fraction of the ar-
ray length and ending at 1, we are led to this compact shellsort implementation.

% java SortCompare Shell Insertion 100000 100


For 100000 random Doubles
Shell is 600 times faster than Insertion

input S H E L L S O R T E X A M P L E

13-sort P H E L L S O R T E X A M S L E
4-sort L E E A M H L E P S O L T S X R

1-sort A E E E H L L L M O P R S S T X

Shellsort trace (array contents after each pass)


260 CHAPTER 2 ■ Sorting

How do we decide what increment sequence to use? In general, this question is a dif-
ficult one to answer. The performance of the algorithm depends not just on the num-
ber of increments, but also on arithmetical interactions among the increments such as
the size of their common divi-
input S H E L L S O R T E X A M P L E
sors and other properties. Many
13-sort P H E L L S O R T E X A M S L E
different increment sequences
P H E L L S O R T E X A M S L E
P H E L L S O R T E X A M S L E
have been studied in the lit-
4-sort
erature, but no provably best
L H E L P S O R T E X A M S L E
L H E L P S O R T E X A M S L E
sequence has been found. The
L H E L P S O R T E X A M S L E increment sequence that is used
L H E L P S O R T E X A M S L E in Algorithm 2.3 is easy to
L H E L P S O R T E X A M S L E compute and use, and performs
L E E L P H O R T S X A M S L E nearly as well as more sophisti-
L E E L P H O R T S X A M S L E cated increment sequences that
L E E A P H O L T S X R M S L E
have been discovered that have
L E E A M H O L P S X R T S L E
provably better worst-case per-
L E E A M H O L P S X R T S L E
L E E A M H L L P S O R T S X E
formance. Increment sequences
L E E A M H L E P S O L T S X R that are substantially better still
1-sort E L E A M H L E P S O L T S X R
may be waiting to be discovered.
E E L A M H L E P S O L T S X R Shellsort is useful even for
A E E L M H L E P S O L T S X R large arrays, particularly by
A E E L M H L E P S O L T S X R contrast with selection sort and
A E E H L M L E P S O L T S X R insertion sort. It also performs
A E E H L L M E P S O L T S X R well on arrays that are in arbi-
A E E E H L L M P S O L T S X R
trary order (not necessarily ran-
A E E E H L L M P S O L T S X R
dom). Indeed, constructing an
A E E E H L L M P S O L T S X R
A E E E H L L M O P S L T S X R
array for which shellsort runs
A E E E H L L L M O P S T S X R slowly for a particular incre-
A E E E H L L L M O P S T S X R ment sequence is usually a chal-
A E E E H L L L M O P S S T X R lenging exercise.
A E E E H L L L M O P S S T X R As you can learn with
A E E E H L L L M O P R S S T X SortCompare, shellsort is much
result A E E E H L L L M O P R S S T X faster than insertion sort and
Detailed trace of shellsort (insertions) selection sort, and its speed ad-
vantage increases with the array
size. Before reading further, try using SortCompare to compare shellsort with insertion
sort and selection sort for array sizes that are increasing powers of 2 on your computer
(see Exercise 2.1.27). You will see that shellsort makes it possible to address sorting
2.1 ■ Elementary Sorts 261

input

40-sorted

13-sorted

4-sorted

result

Visual trace of shellsort

problems that could not be addressed with the more elementary algorithms. This ex-
ample is our first practical illustration of an important principle that pervades this
book: achieving speedups that enable the solution of problems that could not otherwise be
solved is one of the prime reasons to study algorithm performance and design.
The study of the performance characteristics of shellsort requires mathematical ar-
guments that are beyond the scope of this book. If you want to be convinced, start
by thinking about how you would prove the following fact: when an h-sorted array is
k-sorted, it remains h-sorted. As for the performance of Algorithm 2.3, the most im-
portant result in the present context is the knowledge that the running time of shellsort
is not necessarily quadratic—for example, it is known that the worst-case number of
compares for Algorithm 2.3 is proportional to N 3/2. That such a simple modification
262 CHAPTER 2 ■ Sorting

can break the quadratic-running-time barrier is quite interesting, as doing so is a prime


goal for many algorithm design problems.
No mathematical results are available about the average-case number of compares
for shellsort for randomly ordered input. Increment sequences have been devised that
drive the asymptotic growth of the worst-case number of compares down to N 4/3, N 5/4,
N 6/5, . . . , but many of these results are primarily of academic interest because these
functions are hard to distinguish from one another (and from a constant factor of N )
for practical values of N.
In practice, you can safely take advantage of the past scientific study of shellsort just
by using the increment sequence in Algorithm 2.3 (or one of the increment sequences
in the exercises at the end of this section, which may improve performance by 20 to 40
percent). Moreover, you can easily validate the following hypothesis:

Property E. The number of compares used by shellsort with the increments 1, 4,


13, 40, 121, 364, . . . is bounded by a small multiple of N times the number of incre-
ments used.
Evidence: Instrumenting Algorithm 2.3 to count compares and divide by the
number of increments used is a straightforward exercise (see Exercise 2.1.12). Ex-
tensive experiments suggest that the average number of compares per increment
might be N 1/5, but it is quite difficult to discern the growth in that function unless
N is huge. This property also seems to be rather insensitive to the input model.

Experienced programmers sometimes choose shellsort because it has acceptable


running time even for moderately large arrays; it requires a small amount of code; and
it uses no extra space. In the next few sections, we shall see methods that are more ef-
ficient, but they are perhaps only twice as fast (if that much) except for very large N, and
they are more complicated. If you need a solution to a sorting problem, and are work-
ing in a situation where a system sort may not be available (for example, code destined
for hardware or an embedded system), you can safely use shellsort, then determine
sometime later whether it will be worthwhile to replace it with a more sophisticated
method.
2.1 ■ Elementary Sorts 263

Q&A

Q. Sorting seems like a toy problem. Aren’t many of the other things that we do with
computers much more interesting?
A. Perhaps, but many of those interesting things are made possible by fast sorting al-
gorithms. You will find many examples in Section 2.5 and throughout the rest of the
book. Sorting is worth studying now because the problem is easy to understand, and
you can appreciate the ingenuity behind the faster algorithms.
Q. Why so many sorting algorithms?
A. One reason is that the performance of many algorithms depends on the input val-
ues, so different algorithms might be appropriate for different applications having dif-
ferent kinds of input. For example, insertion sort is the method of choice for partially
sorted or tiny arrays. Other constraints, such as space and treatment of equal keys, also
come into play. We will revisit this question in Section 2.5.
Q. Why bother using the tiny helper methods less() and exch()?
A. They are basic abstract operations needed by any sort algorithm, and the code is
easier to understand in terms of these abstractions. Moreover, they make the code di-
rectly portable to other settings. For example, much of the code in Algorithms 2.1
and 2.2 is legal code in several other programming languages. Even in Java, we can use
this code as the basis for sorting primitive types (which are not Comparable): simply
implement less() with the code v < w.
Q. When I run SortCompare, I get different values each time that I run it (and those
are different from the values in the book). Why?
A. For starters, you have a different computer from the one we used, not to mention
a different operating system, Java runtime, and so forth. All of these differences might
lead to slight differences in the machine code for the algorithms. Differences each time
that you run it on your computer might be due to other applications that you are run-
ning or various other conditions. Running a very large number of trials should dampen
the effect. The lesson is that small differences in algorithm performance are difficult to
notice nowadays. That is a primary reason that we focus on large ones!

You might also like