John Murdoch: Here, let me ask you a question. You heard of a place called Shell Beach?
Inspector Frank Bumstead: Sure.
John Murdoch: Do you know how to get there?
Inspector Frank Bumstead: Yeah.
John Murdoch: Tell me.
Inspector Frank Bumstead: Right. You just... you go to the...
John Murdoch: Where? Where do you go?
Inspector Frank Bumstead: Just give me a second, will you...
John Murdoch: You can't remember, can you?
---
John Murdoch: Hey, do you know the way to Shell Beach?
Taxi Driver: You're kidding! Me and the Mrs. spent our honeymoon there. All you gotta do is take Main Street West to... or is it the Cross... You know, that's funny, I can't remember if it's Main Street West or the Crosstown.
---Dark City
The goal of this lab is to give you more practice programming in C and working with the C compiler, to demonstrate three other sorting algorithms, and to to study the efficiency of sorting algorithms experimentally, comparing the results with the theoretical findings of complexity analysis.
Make a directory for this lab and move into it. Copy given the code from the course directory.
mkdir lab2 cd lab2 cp /homes/tvandrun/Public/cs245/lab2/* .
The given files are
array_util.h
and array_util.c
,
the library of useful array functions.
sorts.h
and sorts.c
,
a library of sorting algorithms.
You will be modifying sorts.c
sort_driver.c
, a driver program
to test the sorting algorithms
makefile
, the makefile for compiling
these
experiment.c
, the program for running
experiments.
Note that I am giving you the makefile for this lab. In some future labs and projects, you will need to modify a makefile or write your own from scratch. Open the makefile in a text editor and talk through it with your partner; review what we talked about in class and make sure you understand it, anticipating writing your own sometime in the future.
Your first task is to implement yet another sorting algorithm, called Shell sort. Suppose we have the array
49 7 83 22 8 45 72 91 22 80 53 88 43 29 14 35 55 24 37 84
First consider the items separated by 7 spaces, starting at 0.
49 7 83 22 8 45 72 91 22 80 53 88 43 29 14 35 55 24 37 84
Sort them.
14 7 83 22 8 45 72 49 22 80 53 88 43 29 91 35 55 24 37 84
The items separated by 7 starting at 1 are already sorted.
14 7 83 22 8 45 72 49 22 80 53 88 43 29 91 35 55 24 37 84
Sort the next bunch.
14 7 83 22 8 45 72 49 22 80 53 88 43 29 91 35 55 24 37 84
14 7 55 22 8 45 72 49 22 80 53 88 43 29 91 35 83 24 37 84
Keep doing that until all the array slices with gap 7 are sorted. The actual sorting can be done using a modified insertion sort. Then, we decrease the gap and repeat the process, say sorting all the slices with gap 3. Finally, sort with gap 1, which is just insertion sort, except that this should be close to the best case for insertion sort because the items by now are nearly sorted.
(It might be tempting to call these sections "shells" and pretend that's where the name of the sort comes from. Actually the algorithm was invented by someone named Donald Shell.)
To implement this, we will use an incremental approach
in which you will test your program using the sort driver.
To compile at test at each step, use the make command
.
When your code compiles, use ./sort_driver
to
test various sorting algorithms for correctness.
Try this out now.
make ./sort_driver selection ./sort_driver bubble
Each test should report that "All tests pass." If you're not getting that message, ask for help.
Now test Shell sort (yes, I mean that; even though you haven't written it yet).
./sort_driver shell
You should see many failure messages about tests that did not pass. That's good, becuase you haven't written shell sort yet. If it passed all the tests before you wrote it, then there would be something seriously wrong with your testing apparatus. (If you aren't getting a screenful of failure messages, ask for help.)
Here are the steps:
You may remember the merge sort algorithm from Programming I. In brief the algorithm sorts by
In sorts.c
,
we divide the task into three functions:
mergeSort()
is the function
that sort_driver
will call.
The purpose of mergeSort()
is
to start the recursive process.
It is written for you since it makes use of some C features we
haven't talked about yet.
mergeSortR()
contains the code for the recursive process.
mergeSort()
makes the first call to
mergeSortR()
.
merge()
merges two sorted subarrays.
It is a helper function to mergeSortR()
We did this function in class last week.
Review it now.
Its prototype is
int merge(int array[], int helper[], int start, int stop)
.
Notice that it receives a helper
array as well as
array
.
The helper array is the destination for the merging, since we
can't merge in-place.
Formally for this function:
PRECONDITION: The subarrays inarray[start, midpoint)
andarray[midpoint, stop)
are sorted, wheremidpoint
is halfway betweenstart
andstop
.
POSTCONDITION: The rangehelper[start, stop)
contains the values fromarray[start, stop)
in sorted order.
RETURN: The number of comparisons.
Notice that merge()
does not
copy the values back to array
.
When merge()
returns, array
is unchanged.
merge()
is given for you.
You can test it in isolation with a separate driver:
make merge_driver ./merge_driver
When merge()
is working, then write
mergeSortR()
.
Notice that it, too, receives a helper
array,
which it will pass on to merge()
.
When merge()
returns,
it is the responsibility of mergeSortR()
to copy values back from helper
to
array
.
You can test it with the main driver.
make sort_driver ./sort_driver merge
Don't forget to add code to count the number of comparisons.
The actual comparisons will all happen in merge()
but mergeSortR()
needs to sum and return them.
We have talked about insertion sort in class.
A partially-written implementation is given for you in sorts.c
.
Finish this by writing the inner loop, which inserts an element
into the right position of the sorted section.
The hard part is the guard of the loop.
Think carefully about this.
Test your implementation:
make sort_driver ./sort_driver insertion
Now open the file experiment.c
.
Inspect it with your partner and figure out what is going on
and how it is using the array_util
library.
Ask if there is anything you don't understand.
Remember you will need to write your own experiment
in Project 1.
Compile and run the experiment. You may want to run it several times to see how much variation there is on different runs. What do you observe about the running times of the various sorting algorithms?
Write a brief (paragraph-sized) summary
of what you observed in the experiments
in a file called EXPERIMENTS
.
Make sure your names appear in the files that
the grader will inspect.