Corning Community College
CSCS2320 Data Structures
======Project: OOP0======
=====Errata=====
This section will document any updates applied to the project since original release:
* __revision #__: (DATESTAMP)
=====Objective=====
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.
=====Background=====
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 an 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!
=====Project Overview=====
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 contend 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.
====In inc/Node.h====
First up, let's start with something that, at its core, should be quite familiar:
#ifndef _NODE_H
#define _NODE_H
#include
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.
====In inc/SinglyLinkedNode.h====
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
class SinglyLinkedNode : public Node {
public:
SinglyLinkedNode();
SinglyLinkedNode(int);
virtual Node *copy();
void setAfter(Node *);
Node *getAfter();
~SinglyLinkedNode();
private:
Node *after;
};
#endif
====In inc/DoublyLinkedNode.h====
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
class DoublyLinkedNode : public SinglyLinkedNode {
public:
DoublyLinkedNode();
DoublyLinkedNode(int);
virtual Node *copy();
void setPrior(Node *);
Node *getPrior();
~DoublyLinkedNode();
private:
Node *prior;
};
#endif
====In inc/List.h====
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
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
====In inc/ListOfSinglyLinkedNodes.h====
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
#include
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
====In inc/ListOfDoublyLinkedNodes.h====
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
#include
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
=====Project Requirements=====
For this project, it is your responsibility to:
* Implement all functions in the following classes:
* **Node**
* **SinglyLinkedNode**
* **DoublyLinkedNode**
* **List**
* **ListOfDoublyLinkedNodes**
* Implement the minimally necessary amount of functions in **ListOfSinglyLinkedNodes** to allow **ListOfDoublyLinkedNodes** to work
* Implement unit tests to check the viability of your implementations (I will supply one for analysis).
* by unit test, I mean something rather aggressive that tests many arrangements of valid operations, to ensure correct implementation. You may model after the logic I used in the unit tests you've made use of all semester.
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.
=====Submission=====
{{page>haas:fall2017:common:submitblurb#DATA&noheader&nofooter}}