Assignments | Course Home | Documentation | Lab Hours/Tutoring | Schedule | Submit

Saint Louis University

Computer Science 2100
Data Structures

Michael Goldwasser

Fall 2015

Dept. of Math & Computer Science

Programming Assignment 04

Merging Lists

Due: Wednesday, 28 October 2015, 11:59pm

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.

Collaboration Policy

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.


Contents:


Overview

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

void merge(NodeList& other);
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.

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).


Files We Are Providing

All such files can be downloaded here.


Files to Submit


Grading Standards

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.


Hints

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.


Using Our Driver

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 A = {5, 9, 12} and B = {4, 10, 11, 15}, and then invoke A.merge(B). Hopefully this results in A = {4, 5, 9, 10, 11, 12, 15}.

After that, it will create two lists A = {3, 4} and B = { }, and again call A.merge(B) (which hopefully results in A = {3, 4}).

Then it will merge {-10, 0, 0, 8} and {-5, 8, 10}, hopefully producing the list {-10, -5, 0, 0, 8, 8, 10}. After this, it exits.

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).

Visualizations

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:


Michael Goldwasser
CSCI 2100, Fall 2015
Last modified: Monday, 26 October 2015
Assignments | Course Home | Documentation | Lab Hours/Tutoring | Schedule | Submit