Lab 4: MergeSort and Big-O
Due on Wednesday, October 2nd at 11:59 PM. This is a team lab. You and your assigned lab partner(s) will complete this lab together. Make sure that you are familiar with the Partner Etiquette guidelines. You may discuss the concepts of this lab with other classmates, but you may not share your code with anyone other than course staff and your lab partner(s). Do not look at solutions written by students other than your team. If your team needs help, please post on the Piazza forum or contact the instructor or ninjas. If you have any doubts about what is okay and what is not, it’s much safer to ask than to risk violating the Academic Integrity Policy.
Overview
This lab consists of three primary parts:
-
Implementing and testing the MergeSort algorithm
-
Proving the Big-O complexity of mathematical functions
-
Analyzing and empirically testing algorithms to understand complexity
As you will be working with another student to complete this lab, you will both use the same GitHub repository. You can find a link to your repository on Teammaker, a web application we will use to form teams.
Please remember that both lab partners must learn this material; it will feature prominently on your tests and final exam. Do not divide up this lab e.g. to give one team member the theory material and another member the sorting algorithm. You should be working on all parts together.
Part I: MergeSort
Your starting repository includes the following files:
-
mergeSort.h
/mergeSort.cpp
: The library for your MergeSort algorithm. -
main.cpp
: A small program to use your algorithm to sort command-line arguments. -
tests.cpp
: A file where you will write your unit tests. -
Makefile
: The filemake
uses to understand how to build your project.
Files that you will need to modify are bold.
To complete this lab, you should implement the mergeSort
function in mergeSort.cpp
just as we discussed in class. You’ll need to be careful to follow the algorithm closely and to manipulate array indices accurately. You’ll probably have bugs in your first attempt, so remember the following tools we have discussed for finding and correcting mistakes:
-
gdb
, the debugger that lets you step through your code a little at a time -
valgrind
, the program that helps you find memory errors -
UnitTest++, the unit testing framework (which you are required to use)
Unit Tests
For this lab, you will be graded not only on whether your mergeSort
implementation is correct but also on whether you have properly tested it. You have been provided a couple tests to start, but you are required to write at least four more tests that investigate different aspects of sorting. Some ideas for additional tests include:
-
Sorting a single-element array to make sure nothing bad happens.
-
Sorting an array that is already in order and seeing whether it stays that way.
-
Sorting a large array of numbers that approach a midpoint from opposite directions (e.g.
[0,999,1,998,2,997,…]
). -
Sorting an array in reverse order and seeing whether it winds up sorted.
-
Sorting an array that contains several duplicates to make sure that they are handled properly.
Although you have a minimum number of tests to write, you should ideally write as many as it takes for you to be confident in your code. Remember: each time you change your tests, run make tests
before re-running your ./tests
program.
Coding Style Requirements
As usual, you will also be required to observe good coding practices:
-
Your C++ code must have proper and consistent indentations.
-
You must have proper and consistent usage of spacing & braces for
if
,else
,for
, andwhile
conditions as well as class definitions and code blocks.
For more information about good style, please see the course style guide.
Part II: Written Assignment
In this part of your lab, you will apply the Big-O complexity material that we have discussed in class by writing some Big-O proofs about mathematical functions.
Electronic Submissions Only
In order to complete this assignment, you will need to produce a document containing some mathematical expressions and figures. You will commit and push this document to your GitHub repository; the document may take the following forms:
-
A PDF file named
WrittenLab.pdf
containing formatted text -
A LaTeX file named
WrittenLab.tex
containing formatted text
Your team must submit the document electronically in one of these forms. In particular, you are not permitted to turn in the following (to name a few examples):
-
A raw text document (regardless of formatting)
-
A scan of a written document (even if the scanned document is a PDF)
-
A Microsoft Word file or similar word processor document (although you may write the homework in that format and then export a PDF from it)
-
A piece of paper turned in by hand
A Few Words About LaTeX
LaTeX (pronounced lah-tek or lay-tek) is a document preparation system frequently used to produce conference papers, dissertations, and other academic works (in addition to other material). With LaTeX, you code your document much as you would an HTML document or a Python program. For instance, the LaTeX code
I'm \textit{not} making this up: \(e^{i\pi} = -1\)
produces
You are not required to learn LaTeX for this course. However, it may be easier to use basic LaTeX to complete your homework than to use something like Microsoft Word’s equation editor. In case you’re interested, the following files are already part of your repository:
-
LearningLaTeX.tex
: A LaTeX document with some examples of how to use LaTeX to write the things you need to write in this lab. You should look at the.tex
file before looking at the.pdf
it produces. -
WrittenLab.tex
: A LaTeX document containing your homework problems and places for you to fill them in. These same problems are listed below, but they have been included in this document for your convenience.
Big-O Proofs
Use the formal definition of Big-O notation to prove the following statements:
-
\(4n^2-2n+5\) is \(O(n^2)\).
-
\(3n^3+12n^2-1\) is \(O(n^4)\).
Part III: Mystery Functions
In this part of the lab, you will first analyze six simple loop structures and determine their runtime complexity in terms of Big-\(O\) notation. Then, using the provided program function_timer
, you will graph the empirical runtimes of a these functions in a mixed up order. Your job will be to match your theoretical analysis to the empirical data.
Functions
Begin by identifying the Big-\(O\) runtime for each of the following functions. Provide a brief justification of your answer; a sentence or two should do. Give the strictest Big-\(O\) you can find: don’t give \(O(2^n)\) if the function is also \(O(n)\) and leave out any unnecessary terms (give \(O(n^2)\) rather than \(O(n^2+3)\)).
-
Function fnA(n): For i In 1 To n: Set j To 0 While j < n: Set j to j + 10 EndWhile EndFor EndFunction
-
Function fnB(n): While n > 1: Set n To n/2 EndWhile EndFunction
-
Function fnC(n): For i In 1 to n*50: Set a To i EndFor EndFunction
-
Function fnD(n): Set i To 0 While i < n*n: Set i To i + 1 EndWhile EndFunction
-
Function fnE(n): For i In 1 to n*n: For j In 1 to n*n: Set a To j EndFor EndFor EndFunction
-
Function fnF(n): For i In 1 to n*n: Set j To n While j > n - 10: Set j To j - 1 EndWhile EndFor EndFunction
Using function_timer
to Inspect the Functions
Each of the above functions has been implemented and packaged into an executable function_timer
that was provided to you in your repository for this lab. The function_timer
program will provide empirical runtime data for each function in a form that can be graphed by another tool called gnuplot
.
To use this program, you must pick the following:
-
Which function(s) to plot. For each function, you must provide a command-line argument in the form
-2
,-3
, etc. -
The minimum and maximum values for \(n\). Remember: for slow algorithms, \(n\) should be small or the program may take a very long time. For fast algorithms, you’ll need to give a very large \(n\) or you won’t be able to see anything meaningful on the plot. Start with small \(n\) for each function and work your way up.
For instance, you can graph functions 2 and 3 within \(10 \leq n \leq 100\) by running this command:
./function_timer -2 -3 -n 10 -m 100 | gnuplot
If you get a Permission denied
error when trying to run the above command, then do: chmod u+x function_timer
to make this program executable, and re-try the command.
After a moment, a window will pop up with an image something like this:
Note that this image is an example and will not be what you actually get when you run the same command. Also note the "pipe" character (|
) in the command above; this feeds the output of function_timer
to the input of gnuplot
so it can graph the results for you.
If you want to save the image that gnuplot
makes for you, you can add a -s
parameter to function_timer
like so:
./function_timer -2 -3 -n 10 -m 100 -s "f2,f3 from 10 to 100.png" | gnuplot
Written Response
For this part of the assignment, include in WrittenLab.pdf
the following
parts:
-
A description of which mystery function (
1
,2
, etc.) matches which algorithm (fnA
,fnB
, etc.). -
For each mystery function, a short paragraph describing why you think it matches the algorithm you named.
-
For two of the mystery functions, a graph (saved from
function_timer
) that supports your claims.
Summary of Requirements
You must
-
Implement and test MergeSort
-
Provide a PDF or LaTeX file containing the following:
-
Proofs of the Big-O complexity of the functions described above
-
A Big-O analysis of the pseudocode algorithms given above
-
A matching of these algorithms to mystery functions using
function_timer
-
-
Each student must complete the lab assignment survey as part of the participation grade.