Lecture 14. Shellsort. 10/27/97.
================================================================
In this lecture we look at a sort which can perform well in practice but which has not been completely analyzed. Shellsort is named after its discoverer, Donald Shell.
Shellsort works by sorting sublists of the original list. On the jth pass, the elements of the sublist are determined by an increment hj. For example, if h1 = 4, then on the first pass four sublists are sorted:
list 1: elements 0,4,8,12, ...
list 2: elements 1,5,9,13,...
list 3: elements 2,6,10,14, . . .
list 4: elements 3,7,11,15,...
To implement shellsort we must determine:
1. what should the increments be?
2. what sort should be used on each pass?
3. does shellsort work, i.e., do items in the correct order after one pass reamin in the correct order on successive passes?
4. what is the running time of shellsort? In particular, is shellsort any more efficient than the sorts used on the sublists?
Example (from S. Baase, p. 81):
suppose we sort the following list with increments h1 = 6, h2 = 4, h3 =3, h4 = 2, h5 = 1:
Original list: 7 19 24 13 31 8 82 18 44 63 5 29 sublist: 1 2 3 4 5 6 1 2 3 4 5 6After pass 1: 7 18 24 13 5 8 82 19 44 63 31 29 sublist: 1 2 3 4 1 2 3 4 1 2 3 4
After pass 2: 5 8 24 13 7 18 31 19 44 63 82 29 sublist: 1 2 3 1 2 3 1 2 3 1 2 3
After pass 3: 5 7 18 13 8 24 31 19 29 63 82 44 sublist: 1 2 1 2 1 2 1 2 1 2 1 2
After pass 4: 5 7 8 13 18 19 29 24 31 44 82 63
After pass 5: 5 7 8 13 18 19 24 29 31 44 63 82
Now an algorithm for shellsort, which uses insesrtion sort on the sublists, is given by:
Shellsort(n)for s = 1 to t do
h = hs
for j = h+1 to n-1 do
x = L[j]
k = j - h
while k >= 0 and A[k] > x do
A[k+h] = A[k]
k = k - h
A[k+h] = x
Note that this algorithm there are relly three loops--the outer loop steps through the increments, the loop on j processes all sublists for the given increment, and the innermost loop is performing the sort on the sublist.
In the list A we say that an inversion occurs when two elements, x and y, are out of order.
Exercise 14.1. All of the algorithms in the programming assignment except radix sort work by comparison, i.e., by comparing pairs of elements and swapping if they are not in the right order. For some of the algorithms each swap removes at most one inversion, while for others each swap may remove more than one inversion. Which of the algorithms in the assignment (omitting radix sort) remove inversions one at a time? How does this relate to the running time (worst case and average) of each algorithm?
Note that shellsort has the potential to remove many inversions at once because moving an item in a sublist may also make it closer to its correct position in the entire list.
It can be proved that shellsort is a correct algorithm. In particular, it can be shown that once a sublist is sorted using a particular increment it will remain sorted on successive passes.
A complete analysis of the bahavior of shellsort has not been done. Some known examples include:
If we use two increments, 1.72(n1/2) and 1, then the average running time is "capital theta"(n5/3), i.e., we do better than with strict insertion sort.
If we use a sequence of increments of the form 2k -1 then the worst case running time is O(n3/2).
If increments are integers of the form 2i3i, then the number of comparisons done is
O(n(log2n)2).
Exercise 14.2. Define an order on pairs of integers (a,b) as follows:
(a,b) < (c,d) if either a < c or a=c and b < d.
a. Show that this gives a linear order on pairs of integers.
b. Derive a sorting algorithm for a list of pairs of integers, using this definition of order. Give a worst case running time for your algorithm.