Welcome to your first CS302 lab which consists of two parts that both focus on sorting. In Part A, you implement a data structure for storing multi-column data consisting of a firstname, a lastname, and a phone number (all made up, but you knew that), read unspecified amounts of such data from stdin and apply the std::sort algorithm before you print the result to stdout. In Part B, you implement a variant of the quicksort algorithm described in class that in its basic form replaces std::sort and in a more advanced version allows partitioning of the data followed by sorting within a given range. The latter extension will be based on the quickselect algorithm also described in class. You will also add command line option handling for selecting a particular method.
Read the assignment a couple of times. Look at the output examples below. Run the solution code to become familiar with its behavior. Ask questions on Piazza so the whole class can benefit from your confusion. Chances are you are not alone. Do this for every lab assignment.
Lab submission and due date
Your friendly TAs will tell you how to submit your work to Canvas. Do not email your code to the instructor or the TAs as they cannot upload the code to Canvas for you.
Part A is due 11:59pm Sunday Sep 1, 2019. Part B is due 11:59pm Wednesday Sep 11, 2019. You only submit one file each time. The incremental development outlined below is merely intended to make solving the problem more manageable. All submitted code must compile and execute without seg faulting to be graded.
Aim to submit Part A early, so you get a head start on the command line option handling. That way, you get more time to work on the quicksort and quickselect code.
Getting started and what you need to do
To help you get started, run the Hydra script /home/cs302/labs/lab1/copy to obtain the following files: QsortA.cpp and QsortB.cpp (skeleton code), sqsort (Hydra solution executable), list1.txt-list3.txt (data files), and a makefile. Your job is to write the missing source code which must behave as described next.
Develop your code in stages as described next. QsortA.cpp must contain ALL code needed to first satisfy Part A. You then copy and update this file to satisfy Part B. You will work with multi-file assignments in later labs.
Part A Vers. 1: Use your favorite editor to modify QsortA.cpp as follows. Add code for the input and output operators associated with the data class which has three private data members: firstname, lastname, and phonenumber. The input operator simply reads each of these every time it is called. The output operator prints a data object using the format: lastname firstname phonenumber. See examples below. Part of the assignment is for you to figure out how to maintain a fixed width of the name field so that all phonenumbers are left justified to the same column position. Finally, implement printlist() as a template function that takes generic iterator arguments and steps thru the data while printing to stdout. Do whatever else is needed to make the program compile such as adding missing header files. Then test and make sure it reads and writes data from the list files as required.
unix> QsortA < list.txt
Part A Vers. 2: Add an overloaded operator< to the data class, so you can impose an order on such objects. Test that it works by applying the std::sort algorithm before writing the list content to stdout. Objects that store the same lastname should use the firstnames to determine which is less than the other. Objects that also store the same firstnames should use the phone numbers to determine which is less than the other. See examples below.
This completes Part A. Submit QsortA.cpp on Canvas after you have cleaned the code up and added a few comments.
Part B Vers. 1: Add command line argument handling. When completed, any one of the following three ways of calling QsortB will be valid:
unix> QsortB -stl < list.txt unix> QsortB -rpivot < list.txt unix> QsortB -rpivot k0 k1 < list.txt
The first version executes the code from Part A. The second version uses your own implementation of quicksort to sort the data. The third version partitions the input data as described below before applying quicksort to sort the data in the range given by integers k0 and k1. Without checking, we will assume that k0 is less than k1. Do check if k0 is less than 0, in which case it should silently be changed to 0. Likewise, check if k1 is greater than or equal to the number of elements in the data array, say N, and if so, silently change it to N-1.
Part B Vers. 2: Implement quicksort as follows. Copy the partition_median2() and quicksort_median2() functions from the sorting4 handout. Replace the median-of-three pivot with a randomly chosen index in the left-to-right range and use it to partition the data. This new version forces you to think about how the median-of-three partitioning code works as unlike it, you must now explicitly check and prevent going out-bounds during the search for data pairs to swap. To make you think even more about the algorithm, merge all the functionality into the quicksort() function. That is, do not have an external function that carries out the partitioning. Keep it all in one function that gets called from the main() function. Test and compare the output with what you obtained using std::sort. The two output should be identical since they use the same comparison operator.
Part B Vers. 3: Copy the quickselect() function from the sorting4 handout. Embed the random pivot based partition code that you added to quicksort() in Part B Vers. 2. The function will take four arguments, i.e., quickselect(A, left, k, right) where A is a data array, left and right designate the first and the last indices to consider (the range), and k the element that needs to be selected (found and put in its proper place). Make whatever other modifications are needed to get the code to compile. Test the program to make sure you the selection is correct.
Use quickselect(A, 0, k0, N-1) to put the k0-th element in its proper location and partition the data in A accordingly. That is, ensure that all data stored to the left of A[k0] is lexicographically less than or equal to it. All data stored to the right of A[k0] must likewise be greater than or equal to it.
Then use quickselect(A, k0, k1, N-1) to put the k1-th element in its proper location and partition the data in A accordingly. Note that data indexed below k0 is ignored at this point. When this works, use the quicksort() function to sort the data in the k0 thru k1 index range.
This completes Part B. Submit QsortB.cpp on Canvas after you have cleaned the code up and added a few comments.
Example runs based on list1.txt
unix> cat list1.txt CANDACE WITT 250-939-5404 THEODORE PERKINS 723-668-3397 THAD HULL 708-807-6757 STEPHAN SALAZAR 415-413-5058 ISRAEL WILKINS 938-701-1455 BRUCE PERRY 540-916-2956 VALENTIN RIVERS 726-204-2377 WILFRED JOHNSTON 582-126-8861 JORDAN WILKINS 938-701-1455 LEVI SPENCE 985-365-7415 KAYLA NGUYEN 484-322-1527 unix> ./QsortA < list1.txt [same as below] unix> ./QsortB -stl < list1.txt [same as below] unix> ./QsortB -rpivot < list1.txt HULL THAD 708-807-6757 0 JOHNSTON WILFRED 582-126-8861 1 NGUYEN KAYLA 484-322-1527 2 PERKINS THEODORE 723-668-3397 3 PERRY BRUCE 540-916-2956 4 RIVERS VALENTIN 726-204-2377 5 SALAZAR STEPHAN 415-413-5058 6 SPENCE LEVI 985-365-7415 7 WILKINS ISRAEL 938-701-1455 8 WILKINS JORDAN 938-701-1455 9 WITT CANDACE 250-939-5404 10 unix> ./QsortB -rpivot 3 6 < list1.txt JOHNSTON WILFRED 582-126-8861 0 HULL THAD 708-807-6757 1 NGUYEN KAYLA 484-322-1527 2 PERKINS THEODORE 723-668-3397 3 ** PERRY BRUCE 540-916-2956 4 ** RIVERS VALENTIN 726-204-2377 5 ** SALAZAR STEPHAN 415-413-5058 6 ** SPENCE LEVI 985-365-7415 7 WILKINS ISRAEL 938-701-1455 8 WITT CANDACE 250-939-5404 9 WILKINS JORDAN 938-701-1455 10
The line numbers added to right for the last output are for illustrational purposes and not produced by the program. They help you see that the data in lines 3-6 is sorted (by design), that the data lines 0-1 and 9-10 is not, and that the data in lines 2 and 7-8 is (by chance).
Note: Output format of your program must MATCH that of the solution executable. Use the diff command to compare.
Quicksort Part A (50)
25: Class data: operator>> and operator<< 15: Class data: operator< 10: Function printlist()
Quicksort Part B (150)
20: Command line argument handling: 30: Quicksort: random pivot, integrated partitioning while-loop safety guard(s) 20: Quickselect: random pivot, integrated partitioning, while-loop safety guard(s) 15: Output matches solution code output for list1.txt, list2.txt and list3.txt 15: Goldielocks comments: not too many, not too few -- just the right amount