Project: Basic ADTs

The goals of this project are to re-familiarize yourselves with common ADTs, to begin thinking about implementation questions, to underscore the distinction between abstract and concrete, and, generally, to review writing classes in Java.

This project typifies how projects will tend to be like in this course (except that subsequent projects will tend to be more difficult): Implement a data structure or algorithm (or series of data structures and algorithms), testing them with given test cases.

1. Set up

Copy the given code for this project from ~tvandrun/Public/cs345/adt-review and make an Eclipse project for it. If you find yourself needing detailed instructions, you'll find this project used as the example in the general project guide for this course. I won't be giving instructions on project set-up from this point on.

This project's packages typify how most of this course's project will be structured. It has three packages, adt for the interfaces of the ADTs used in the project---in this case, the "canonical" ADTs; impl for the classes that implement the ADTs with specific strategies, some of which are stubs for you to complete; and test for the JUnit tests. (Some future projects will also have packages alg and exper for classes containing static methods implementing algorithms and classes containing experiments, respectively.)

In this project, most of the implementations are wrappers that use another ADT as their underlying implementation, somewhat like the Adapter pattern.

Note that the naming convention for classes in the impl package are XY where Y is the ADT being implemented and X is the strategy being used, which could be either a concrete data structure or another ADT. Thus ArrayMap is a map built using an array inside, and MapList is a list using a map (in theory, any map) inside.

The classes you are given to complete already have instance variables. You may add more instance variables (in fact, in some of the classes you will need to add at least one instance variable), but you may not change the basic implementation strategy, described in each task.

In none of these tasks (or any other project in this course) should you in any way change the public interface of the classes, including the signatures of their constructors, and do not change any of the classes that you are not told to finish (except perhaps for debugging purposes, but be careful and be able to undo those changes). You will not be turning in the whole project but only the classes you are told to modify. Your submission will be graded based on how it works with the original forms of the other classes in the codebase.

2. Implementing ArrayMap

Your first task is to finish ArrayMap. For convenience I have provided a nested class for key/value pairs and declared an instance variable for an array of these. Also for convenience I have written the constructor to make an initial array and given a helper method to make the array grow. You may modify this as long as it retains the basic strategy of using an array (or arrays). For example, you may choose to have two parallel arrays (one for keys, one for values) instead of an array of pairs---but you may not use ArrayList or any other off-the-shelf component, and you may not use a linked-list approach.

You can test your class using AMTest; the code test cases themselves can be found in the parent class MapTest. I recommend inspecting the tests to figure out which correspond to which Map methods and use that to determine a sensible order in which to implement the methods in ArrayMap and test as you go. (You should always be looking for new test cases at add.)

3. Implementing MapSet

Next finish MapSet. You will first need to figure out how a map can be used to implement a set, but once you have done that this task is "easy." Keep in mind that although the JUnit test cases will test MapSet by giving it an instance of your ArrayMap from last time, the implementation of MapSet should not depend on the implementation details of ArrayMap---it should depend only on the Map interface.

Your implementation must use a Map as its underlying container (already present in the given instance variable internal, but you may add primitive-typed instance variables if necessary.

(Hint: The second type parameter to Map in the declaration of internal is String. That was largely an arbitrary choice. Almost any class would do.)

Test using MSTest; the actual tests are in the parent class MapTest.

4. Implementing MapList

Finish MapList; similar rules apply. (Hint: Notice that the key type of internal is int. Think about how a map can be thought of as a generalization of a list.)

Test using MLTest, a child class of ListTest.

5. Implementing ListBag

Finish ListBag; similar rules apply. This will be tested using a MapList which in turn uses an ArrayMap. See the given Bag interface for details of the specification.

Test using LBTest, a child class of BagTest.

6. Epilogue: ListQueue and ListStack

The last two are already given to you, but you should make sure that LQTest and LSTest run correctly using your MapList as the underlying implementations for these two classes.

7. Turn-in

Copy the files you modified (ArrayMap, MapSet, MapList, and ListBag) to your turn-in folder /cslab/class/cs345/(your id)/adt-review .

To keep up with the course, this should be finished by Jan 26.


Thomas VanDrunen
Last modified: Thu Jan 5 16:22:50 CST 2017