Corning Community College
CSCS2320 Data Structures
~~TOC~~
This section will document any updates applied to the project since original release:
In this project, we pursue our third rewrite of linked list code, this time implementing such functionality within an object-oriented fashion using C++ (in true OOP form, and not as a lazy C!)
This also serves as part of the End of Course Experience, which wraps up our Data Structures journey this semester.
Hopefully by now, we have all grown rather familiar with the basic concepts surrounding nodes and linking them together, and all the fun/attention to detail/number of details/variations that can offer to problem solving.
As a means of furthering our conceptual understanding, while also gaining valuable programming experience, we will now undergo a rewrite in on object-oriented fashion, pursuing more than just the superficial objects/classes that are barely a third of the object-oriented experience.
And what are the other two-thirds? Why, inheritance and polymorphism, of course!
For this project, we're going to be implementing a linked list data structure utilizing nodes. Predominantly one should notice many similarities of conceptual flow– since we are just re-implementing something we've done twice before.
The big differences are syntactical and object-oriented conceptual. One thing we now have to content with is access control, which adds another layer of detail to things. But that also offers us some advantages.
Also, note the case, especially as “camel case” (ie the capitalization of first letters of words, frequently words that are smashed together to form a more descriptive variable name)… this tends to be part of the object-oriented programming culture, even if it isn't required by the language proper or any of its development tools.
First up, let's start with something that, at its core, should be quite familiar:
#ifndef _NODE_H #define _NODE_H #include <cstdlib> class Node { public: Node(); Node(int); void setValue(int); int getValue(); virtual Node *copy() = 0; virtual void setAfter(Node *) { }; virtual Node *getAfter() { return (NULL); }; virtual void setPrior(Node *) { }; virtual Node *getPrior() { return (NULL); }; virtual ~Node(); private: int value; }; #endif
The OOP Node class is now part of a hierarchy, and as such, is what is known as an abstract base class… what might seem weird, is this is really only a base reference point, we won't actually be making any Node objects (we can't, nor would we want to– Node as a class isn't actually useful), but deriving child classes from this class. And we will want to instantiate those derived classes.
But- to add a twist, through C++'s ability to upcast base class pointers and taking advantage of polymorphism, we will access the child class functionality THROUGH this class, keeping the naming simpler.
The first node class we can make use of is that of the Singly Linked Node. Here, we see that the SinglyLinkedNode class inherits from Node, and in similar style, incorporates content from its parent class, and adds new functionality (specifically, the after pointer). So, SinglyLinkedNode is similar to the nodes used in the earlier parts of the semester.
Note that, due to access control, the ability to read/write the after pointer will be restricted outside of this class. As such, we implement two accessor functions: setAfter() and getAfter(), which will do the sanctioned and heavy lifting to allow outside parties access.
#ifndef _SINGLY_NODE #define _SINGLY_NODE #include <Node.h> class SinglyLinkedNode : public Node { public: SinglyLinkedNode(); SinglyLinkedNode(int); virtual Node *copy(); void setAfter(Node *); Node *getAfter(); ~SinglyLinkedNode(); private: Node *after; }; #endif
The DoublyLinkedNode class gets our node capabilities back to how we've been dealing with them of late– a node containing a value that has 2 pointers: after and prior
Due to inheritance, we get the value element stuff from the base Node class. We then get all the after element stuff from the SinglyLinkedNode class. As a result, DoublyLinkedNode is an extension of SinglyLinkedNode, which is itself an extension of the base Node class.
#ifndef _DOUBLY_NODE #define _DOUBLY_NODE #include <SinglyLinkedNode.h> class DoublyLinkedNode : public SinglyLinkedNode { public: DoublyLinkedNode(); DoublyLinkedNode(int); virtual Node *copy(); void setPrior(Node *); Node *getPrior(); ~DoublyLinkedNode(); private: Node *prior; }; #endif
Now that we have the classes needed to create and manipulate nodes, we move onto classes that oversee the coordinated manipulation of nodes– referenced from a new container letting us keep track of where to begin and to end, along with how many nodes are a part of this effort. We've come to call these 'lists', due to their sequential nature.
The List class is another abstract base class, meaning we cannot instantiate it, but it will provide some of the core building blocks so that it can be inherited into derived classes and used.
#ifndef _LIST_H #define _LIST_H #include <Node.h> class List { public: List(); virtual List *copy() = 0; int getQuantity(); virtual void append(Node *, Node *) = 0; virtual void insert(Node *, Node *) = 0; virtual Node *obtain(Node *) = 0; virtual void display(int) = 0; virtual Node *find(int) = 0; virtual Node *getFirst() = 0; virtual Node *getLast() = 0; virtual ~List(); protected: void setQuantity(int); virtual void setFirst(Node *) = 0; virtual void setLast (Node *) = 0; virtual Node *setListPosition(int) = 0; virtual int getListPosition(Node *) = 0; private: int quantity; }; #endif
Here the ListOfSinglyLinkedNodes class is the analog to what we called a Singly-Linked List earlier in the semester. It has first and last pointers, it maintains a quantity, and it implements operations to maintain the consistency of this particular grouping of nodes (the ability to insert(), append(), and obtain() nodes in a sane fashion, along with other helpful member functions).
#ifndef _SINGLY_LIST_H #define _SINGLY_LIST_H #include <List.h> #include <SinglyLinkedNode.h> class ListOfSinglyLinkedNodes : public List { public: ListOfSinglyLinkedNodes(); virtual List *copy(); virtual void append(Node *, Node *); virtual void insert(Node *, Node *); virtual Node *obtain(Node *); virtual void display(int); virtual Node *find(int); Node *getFirst(); Node *getLast(); virtual ~ListOfSinglyLinkedNodes(); protected: void setFirst(Node *); void setLast (Node *); virtual Node *setListPosition(int); virtual int getListPosition(Node *); private: Node *first; Node *last; }; #endif
With the “List Of Doubly Linked Nodes”, we see an Object-Oriented C++ implementation of the data structure we affectionately came to know as the “Doubly Linked List”– ie a list of nodes connected to both their immediate after and prior neighbors.
#ifndef _DOUBLY_LIST_H #define _DOUBLY_LIST_H #include <DoublyLinkedNode.h> #include <ListOfSinglyLinkedNodes.h> class ListOfDoublyLinkedNodes : public ListOfSinglyLinkedNodes { public: ListOfDoublyLinkedNodes(); virtual List *copy(); virtual void append(Node *, Node *); virtual void insert(Node *, Node *); virtual Node *obtain(Node *); virtual void display(int); virtual Node *find(int); virtual ~ListOfDoublyLinkedNodes(); protected: virtual Node *setListPosition(int) { return (NULL); }; virtual int getListPosition(Node *) { return (-1); }; }; #endif
For this project, it is your responsibility to:
For those interested in an extra credit opportunity (especially to make up for a missed project), you may fully complete both the functions and create unit tests to bring the ListOfSinglyLinkedNodes class fully on-line.
When you are done with the project and are ready to submit it, you simply run make submit:
lab46:~/src/data/PROJECT$ make submit ...
To be successful in this project, the following criteria must be met: