- Shell Sort. Shell Sort is our first example of
a
non-quadratic sorting algorithm. Its speed-up is due to the fact that
elements in the array move larger distances toward their rightful
places
at each step.
- Shell Sort is a variation of Insertion Sort in which we only look
at
elements that are a particular increment apart each time insertion sort
runs. When elements are shifted, they move a distance equal to that
increment.
- Shell Sort uses a set of increments that decrease in size with
the
final increment equal to 1. By the time the increment of 1 is used, the
array is almost already sorted. Suppose that we use the increments {40,
13, 4, 1}. After we use the increment of 40 we say that the array
is 40-sorted, and after the next pass we say that the array is
13-sorted,
etc. The array is completely sorted after we finish the pass with an
increment of 1.
- Here is one version of Shell Sort pseudocode:
d = n;
while (d > 1)
{
if ( d < 5) d = 1;
else d = (5*d-1)/11;
/*** Do linear insertion sort in steps size d ***/
for ( i = n - 1; i >= n-d; i-- )
{
temp = array[i];
for ( j = i-d; j >= 0 && temp < array[j]; j -= d )
array[j+d] = array[j];
array[j+d] = temp;
}
}
- Use Shell Sort to sort the following:
3 2 9 1 3 2 9 8 2 6 4 3 7 2 1
- Merge Sort. Merge Sort is our first example of a recursive
sorting algorithm that uses
the divide-and-conquer approach. It
repeatedly
divides the array in half, calls Merge Sort on each half and then calls
a
merging function to put the two halves back together into a sorted
whole.
- Any divide-and-conquer algorithm that divides the job in half
and takes no more than n steps to either divide or glue the halves
together
takes approximately n log_{2}(n) steps. This describes
Merge Sort because it takes only n steps to carry out the merge of two
sorted array pieces.
- Here is the code for Merge Sort:
void sort(int numarray[], int low, int high)
{
int bottom = low, top = high;
if (bottom >= top) return;
int mid = (bottom + top)/2;
sort(numarray, bottom, mid);
sort(numarray, mid+1, top);
int endlow = mid, starthigh = mid+1;
while (bottom <= endlow && starthigh <= top)
{
if (numarray[bottom] <= numarray[starthigh])
bottom++;
else
{
int temp = numarray[starthigh];
for (int counter = starthigh-1; counter >= bottom; counter--)
numarray[counter+1] = numarray[counter];
}
numarray[bottom] = temp;
bottom++;
endlow++;
starthigh++;
}
}
- Use Merge Sort and make a few passes on the following data:
3 2 8 10 14 1 2 1 0 15 3 2 5 7 11
- Quicksort. On average, Quicksort is the fastest sorting
algorithm
known for sorting random data. It, too, is a divide-and-conquer
algorithm
but unlike Merge Sort, Quicksort does the majority of its work to
accomplish
a divide. If Quicksort gets lucky, it divides the array nearly in half.
If not, one piece will be substantially larger than the other. If this
latter
size inequality occurs at every recursive step, Quicksort will not
perform
well. It will be no better than a quadratic sorting algorithm.
- In order to divide the array, Quicksort selects one element of
the array
and uses it to compare to all the others. This one particular element
is
called the pivot. Quicksort swaps elements around in the array
to
divide it into two portions. All the elements less than the pivot are
placed in the leftmost portion, all elements greater than the pivot are
placed in the rightmost portion, and the pivot is in between. There may
be elements equal to the pivot in either portion. The process of
dividing the array
into these two pieces is called partitioning the array.
- Once Quicksort partitions the array, it recursively partitions
each of
the two pieces and then partitions each piece of those, etc. Generally,
when
a piece reaches a certain minimum size, Quicksort stops recursing and
calls
a simpler sorting algorithm like insertion sort to complete the work on
that piece.
- Here is one implementation of Quicksort:
void sort(int numaray[], int low, int high)
{
int bottom, top, pivot, temp;
if (high >= low)
{
pivot = numarray[high];
bottom = low - 1;
top = high;
while (true)
{
while (numarray[++bottom] <= pivot &&
bottom < numarray.length);
while (numarray[--top] >= pivot && top > 0);
if (bottom >= top) break;
temp = numarray[bottom];
numarray[bottom] = numarray[top];
numarray[top] = temp;
}
temp = numarray[bottom];
numarray[bottom] = numarray[high];
numarray[high] = temp;
sort(numarray, low, bottom-1);
sort(numarray, bottom+1, high);
}
}
- Use Quicksort to partition the following array a few times:
15 3 5 5 7 1 2 11 3 4 3 9 7 10 20 11 3 2