Beginning Class Hierarchy
The hierarchy has grown. Most of the classes in the package extend Object.
Final Class Hierarchy
All of the data structures are unbounded, including the array implementations which expand as needed. All structures use dynamic allocation.
Two doubly-linked lists are implemented, one that maintains a sorted order and one that doesn't. The SortedLinkedList does not except duplicates and the OrderedLinekList does. The common functionality to both linked lists resides in the abstract class LinkedList. As the diagram shows, multiple inheritance is in use.
Two array based lists are implemented, following the same pattern as the linked lists. Most of the common functionality between the two concrete classes resides in ArrayList. The SortedArrayList makes use of binary searching for retrieval and for insertion.
The Queue and Stack implementation can be composed with either a OrderedArrayList or and OrderedLinkedList, using the factory methods provided. QueueImpl contains functionality that demonstrates the difference between deep and shallow copying.
Unit tests have been refactored to take advantage of the polymorphic nature of the framework. As shown in the above diagram, for example, all list classes have a common parent called List (oddly enough). There is a unit test called container_test::List_test that enforces the List contract for all known sub-classes.
Final Class Hierarchy
So, coming from a Java frame of mind, Container classes will not make copies of the Entity objects stored within them. Only copies of pointer values will be made when an Entity is added. The Container classes will take responsibility of deleting any Entity objects they have a reference to at the time of Container destruction.
Sample Output
LinkedList and Entity - Unit Test Output
The unit tests verify and assert more than is being reported in the print statements. For example, two methods from LinkedList_test generated the above output:
Normally, unit tests aren't designed for human eyes. They either pass or fail, much like code compilation which either succeeds or fails.
Well written unit tests do not require print statements. When they fail, the output is designed to be sufficient to trace the problem to its source. The googletest framework is good in this respect. Upon failure, it prints line numbers, expected values, actual values, etc, that make print statements superfluous in a real development environment.
For example, with NetBeans you can create a Hello World program with a few clicks and then run it by pressing the big green arrow. This is true for a simple console application, a GUI desktop application, a web application, etc. For a web application, it fires up the web server for you a and pops open a browser running the new code, all with the friendly green arrow. Just press play.
Unit tests are just as easy, right out of the box. Select the class to be tested and NetBeans generates a JUnit class with a stub for each method. All you have to do is fill in the stubs. Unit tests can be run with a click of the mouse and become a natural part of the build process.
I started using Subversion for CS-114. Access to source code is served up via HTTP from my laptop computer. I have a development environment at home and at work, which serves as protection against loss and forces me to check in code frequently. In doing so, I have a full history of my project since its inception, with useful check-in comments about what was changed any why.
The NetBeans integration allows for each line to be traced back to the responsible developer and the revision where the line was last changed. This is not a special read-only view. The following shot is of "live" editable code:
Annotated Code With UserID and Version Number
It took me a long time to get NetBeans to compile and run a simple program, partly because it has been so long since I have had to worry about include files, linking, and other concerns that either don't exist in Java or are taken care of by the toolset. Yes, I know, I've grown soft. The first linking error really took me back to the old days, "Oh yeah, these. My favorite."
I ended up with two NetBeans projects. "Structures" for the actual code and "Structures_test" for the unit tests. The source code in "Structures" has no dependency on the unit tests. It compiles down to a library called "libstructures.a" (no executable).
Project "Structures_test" has a build dependency on "Structures". So with a click of a button all files are compiled, linked, and unit tests are executed. The magic is performed by Google's "gtest_main.a" which has a main function that does the work of finding and executing all unit tests.
I also came across an online text book, "Data Structures and Algorithms with Object-Oriented Design Patterns in C++", by Bruno R. Preiss. It has snippets of code but the source is not available.