Algorithms and OOD (CSC 207 2014F) : Labs

Merge Sort


Summary: We continue our exploration of sorting algorithms by considering the famous merge sort algorithm.

Prerequisite Knowledge: The sorting infrastructure, covered in the lab on quadratic sorts.

Preparation

If you have not done so already, fork and clone the repository at https://github.com/Grinnell-CSC207/sorting.

Exercises

Exercise 1: Code Reading

The file MergeSorter.java has a partial implementation of the standard recursive merge sort algorithm.

a. Why do you think we call Arrays.copyOfRange before doing the recursive calls to sort?

b. Why is the program so short?

c. Create a short experiment for the sort method in MergeSorter.java. Minimally, you should write a class whose main method builds a MergeSorter, builds an array, builds an appropriate comparator, calls the sort method using the array, and then prints the result.

d. Do you expect the algorithm/method to work correctly? Why or why not?

e. Check your answer experimentally.

Exercise 2: Implementing merge

As you have probably discovered, the merge sort algorithm doesn't work as currently implemented. Why? Because the Utils.merge method is not implemented.

a. Sketch invariants for the merge method. You will likely want to draw pictures of the three arrays that you'll be working with. You'll also likely have an index into each array that you'll want to keep in the sketch.

b. Based on your invariants, implement that method.

c. You can choose to write experiments and tests for Utils.merge or you can hope that the experiment and tests for MergeSorter.sort will help you identify any errors you might have.

For Those With Extra Time

If you find that you have extra time, attempt one or both of the following.

Extra 1: Counting the Steps in Merge Sort

Merge sort is supposedly an O(nlog2n) algorithm. But it's sometimes useful to gather data to see if the actual performance matches the expected performance.

a. Augment Utils.java to add a step counter. Each time you do an assignment to the array in merge, increment that counter.

b. Write an experiment in which you build random arrays of size 100, 200, 400, 800, and 1600 and have the program count the number of assignments required for each size. (Don't forget to reset the counter between arrays!)

c. Sketch a graph of your data to see if you get the expected behavior. (For an O(nlog2n) algorithm, we'd expect that the running time of the algorithm would slightly more than double each time we double the input size.

d. Do you think counting the number of times we put a value in the result array is a reasonable proxy for the number of steps? Why or why not?

Extra 2: Iterative Merge Sort

Iterative merge sort is an algorithm that works bottom up, rather than top-down. First you merge neighboring elements into sorted pairs. (You may have one element left at the end.) Then you merge all neighboring sorted pairs into sorted 4-tuples. (You may have a singleton, pair, or triple left over.) Then you merge all neighboring sorted 4-tuples into sorted 8-tuples. (You may have a tuple of size less than eight left over.) And so on and so forth.

IterativeMergeSorter.java has a sketch of this algorithm. Finish implementing the algorithm.

Note that you may find it helpful to draw a picture of the expected state of the system before and after one round. And yes, such a picture serves as a form of loop invariant.