Saint Louis University |
Computer Science 2100
|
Dept. of Math & Computer Science |
Please see the general programming webpage for details about the programming environment for this course, guidelines for programming style, and details on electronic submission of assignments.
For this assignment, you must work individually in regard to the design and implementation of your project.
Please make sure you adhere to the policies on academic integrity in this regard.
In this assignment, we wish to add another of the std::list behaviors into our NodeList class. Specifically, the merge method (documented here), has a signature that for our class will appear as
A precondition to this function is that the values on the original list are sorted in non-decreasing order, and that the values on the other list are also sorted in non-decreasing order. After a call to merge, all elements should be in the first list, and the second list should be empty.void merge(NodeList& other);
Note well that the documentation for the official function states
The operation is performed without constructing nor destroying any element: they are transferred.
The iterators, pointes and references that referred to transferred elements keep referring to those same elements, but iterators now iterate into the container the elements have been transferred to.
We insist that your implementation provide a similar guarantee. What this means for your implementation is that you must internally relink the Node's to accomplish the relocation of nodes from the secondary list to the primary list.
The high-level algorithm for merging two sequences is described in Chapter 11.1.2 of the book (in the context of a recursive sorting algorithm known as mergesort). You may use the same ideas in your program, but note that you are to merge the elements from the secondary list into the primary list, while the book's description assumes that two lists are being merged into a third list.
We prefer to paraphrase the algorithm in our context as follows. The merging is performed by simultaneously traversing the two lists from beginning to end. While traversing the other list, if the current element being considered in the other list is less than the current element being considered in the first list, the node with that element is removed from other and relinked into the proper location in the first list. In contrast, if the element currently being examined in the first list is less than that of the other list, than the traversal of the first list advances. This operation is repeated until either end is reached, in which moment the remaining elements of other (if any) are moved to the end of the list object and the function returns (this last operation is performed in constant time).
All such files can be downloaded here.
NodeList.h
This is our original implementation of the NodeList class,
including a new stub for the merge function,
yet without any code.
NodeListVisualizer.tcc
Some support for generating visualizations of the linked lists
(see discussion of driver below).
MergeTest.cpp
This file provides a main driver to be used in testing your
program. You will not need to modify or examine this code. The
use of the driver is discussed in a later section.
makefile
This makefile should allow you to rebuild your project by
simply typing 'make' rather than in invoking the compiler
directly.
Your revised NodeList.h source code
Test Input
Please submit a single file, inputfile, which we will
use as sample input when testing all of the students'
submissions. The file format for inputfiles is based on use with our driver
Your input file may use at most 100 lines (although you may
certainly specify multiple merges within the 100 line limit).
In order to make sure that your inputfile follows the proper
format, we strongly recommend that you make sure that your
inputfile is accepted by the driver.
Readme File
A brief summary of your program, and any further comments you
wish to make to the grader.
The assignment is worth 20 points. Sixteen points will be awarded based on our own evaluation of your assignment and the readme file. Two additional points will be awarded fractionally based on how well your program performs on other students' test inputs. The final two points will be awarded fractionally based on how well your test input fools other students' flawed programs.
In order to maintain the validity of any of the user's iterators after the merge, it is imperative that you not destroy or create any nodes. This means that you cannot rely on any of the existing functionality for methods insert, erase, or any of the various push/pop methods. Instead, you must directly manipulate the underlying nodes of both lists and adjust the relevant next and prev pointers of those nodes to accomplish the merge.
Although the outward challenge to this project is in maintaining the validity of the user's iterators, we wish to emphasize that you do not need to directly use iterators in any part of your code. In authoring the merge method of the NodeList class, you have full rights to all private aspects of the underlying implementation and so your code is most naturally written by making direct use of the Node objects. You can refer to expressions such as header, trailer, other->header, other->trailer as well as the next and prev pointers of any nodes that are part of the lists.
The executable MergeTest is a driver which will handle reading the input, creating the initial lists, calling your routine, and then outputting the merged result.
The expected format for input is as follows (please make sure that the inputfile you submit adheres strictly to these standards!):
You will notice that this format allows you to specify a test file which involves many different merges, as demonstrated in the following example of a properly formatted input file.
5 9 12 1000 4 10 11 15 1000 3 4 1000 1000 -10 0 0 8 1000 -5 8 10 1000 -1000
The driver will create the two lists
After that, it will create two lists
Then it will merge
By default, the driver reads input from the keyboard. However, if you would like to have the driver read input from a text file, you may create such a file, and then give the filename as a single argument when starting the program (as was done in an earlier programming assignment).
As an experiment, we are trying a system to produce graphical visualizations of the before and after state of the linked list. There is no stanard graphics package included with C++, but we will be using a third party tool named Graphviz to produce postscript renderings. This software is already installed on turing.
When you type 'make' to compile your project, it builds two executables by default: MergeTest and MergeTestVisual. The latter is identical to the former except that it also produces images of the two lists just before and after the call to merge. When running this program, it will produce a postscript file merge.ps in the current directory just before calling merge. It updates that file just after calling merge. You may view that file in a separate window. For example, here is the rendering of the first test case just before the merge:
If all goes well, just after the merge, you should get the result:
Of course, if things go poorly, you might get an inconsistent state. Assuming that the call to merge returns without crashing, we will do our best to draw a flawed state, such as: