In this lab you will implement three different sorting algorithms: insertion sort, quicksort and merge sort. You will also compare their performance on various sorts of input data.

The main file

Start by downloading Lab1.java. This file is where you will put your three sorting algorithms. Opening it, you will see three sorting methods:

public static void insertionSort(int[] array)
public static void quickSort(int[] array)
public static int[] mergeSort(int[] array)

At the moment, these three are just skeleton implementations that throw an UnsupportedOperationException when called. Your main job is to finish the implementations.

Just below these three methods, you will find skeleton implementations of some helper methods that you might find useful:

There is also a method void swap(int[] array, int i, int j) that swaps two elements of an array, that you may find useful. It is already fully implemented.

The benchmark tool

You should also download Bench.java. This is a benchmarking program for your three implementations. To run it, compile both Lab1.java and Bench.java and run the Bench class. You can already run it: try it and it will print out a benchmark report consisting of lots of tables. Right now they all look like this:

Arrays of length 1000
=================================================================
Algorithm      |         Random |     95% sorted |         Sorted
Insertion sort |              - |              - |              -
Quicksort      |              - |              - |              -
Merge sort     |              - |              - |              -

This particular table shows the performance of the three algorithms for arrays of 1000 elements (see the heading at the top). Because you haven’t implemented any of the algorithms yet, all of the table cells are filled with dashes, but eventually it will look more like this:

Arrays of length 1000
=================================================================
Algorithm      |         Random |     95% sorted |         Sorted
Insertion sort |       0.242677 |       0.022095 |       0.002044
Quicksort      |       0.045372 |       0.042710 |       0.455633
Merge sort     |       0.075152 |       0.050483 |       0.047600

The benchmark program tries your algorithms on three sorts of data:

All times are reported in milliseconds. So here we can see that insertion sort took 0.242ms for a random list of 1000 elements while quicksort on a 95% sorted list of 1000 elements took 0.0427ms.

Once you have implemented one of the algorithms, you can re-run Lab1.java and the numbers for that algorithm will be filled in. If there is a bug in your algorithm, the table will not contain numbers, but rather a description of what went wrong:

The testing tool

Probably your implementation will have bugs at first. At least, mine did! In that case, the benchmark report will just say INCORRECT or EXCEPTION. Not very helpful!

To help you track down bugs, there is a testing program, Test.java. This program tests a sorting algorithm on arrays of various sizes and prints a message when it goes wrong. You need to tell it what algorithm to use: near the top of the file there is a line that reads Bench.insertionSort. By changing it to Bench.quickSort or Bench.mergeSort you can change which algorithm is tested. After doing that, just compile all three .java files and run the Test class.

A sample output of the testing program is:

Testing on arrays of size 0...
Testing on arrays of size 1...
Testing on arrays of size 2...
Failed!
Input array: {2, 4}
Expected answer: {2, 4}
Actual answer: {2, 0}

This shows that we tried to sort the array `{2, 4}, which should give the result {2, 4}. However, the sorting algorithm mistakenly gave the answer {2, 0}. Once you have this test case, you could for example add a main method to Lab1.java that just tries this particular test case, then add println statements to trace execution and see what goes wrong. Or you can debug your implementation in an IDE.

Note that if your algorithm is correct, the testing program will just try out bigger and bigger arrays until the end of time. So you should only use it if the benchmarking program reports a problem.

Your job

Your first job is to implement the three sorting algorithms as follows:

You will probably find the existing skeleton code and helper methods useful, but they are only a suggested way to structure your implementation: if you have a better idea, go for it! But you must not change the types of the sorting methods themselves.

Once all the algorithms are working, your second job is to compare their performance by looking at the benchmark results. It’s up to you what you look at, but in the end you should write a few sentences to say when you would recommend each algorithm. Questions you could answer include:

Submission

You should submit the following things to Fire:

Your submission will be rejected if: