User Tools

Site Tools


Sidebar

projects

haas:fall2014:data:projects:eoce0

This is an old revision of the document!


Corning Community College

CSCS2320 Data Structures

~~TOC~~

Project: EOCE0

Errata

This section will document any updates applied to the project since original release:

  • revision #: <description> (DATESTRING)

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 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!

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

In inc/Node.h

First up, let's start with something that, at its core, should be quite familiar:

1
#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  setNext(Node *) { };
        virtual Node *getNext()       { return (NULL); };
        virtual void  setPrev(Node *) { };
        virtual Node *getPrev()       { 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 next 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 next pointer will be restricted outside of this class. As such, we implement two accessor functions: setNext() and getNext(), which will do the sanctioned and heavy lifting to allow outside parties access.

1
#ifndef _SINGLY_NODE
#define _SINGLY_NODE
 
#include <Node.h>
 
class SinglyLinkedNode : public Node {
        public:
                         SinglyLinkedNode();
                         SinglyLinkedNode(int);
                virtual Node *copy();
                void setNext(Node *);
                Node *getNext();
                        ~SinglyLinkedNode();
 
        private:
                Node *next;
};
 
#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: next and prev

Due to inheritance, we get the value element stuff from the base Node class. We then get all the next 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.

1
#ifndef _DOUBLY_NODE
#define _DOUBLY_NODE
 
#include <SinglyLinkedNode.h>
 
class DoublyLinkedNode : public SinglyLinkedNode {
    public:
        DoublyLinkedNode();
        DoublyLinkedNode(int);
        virtual Node *copy();
        void setPrev(Node *);
        Node *getPrev();
        ~DoublyLinkedNode();
 
    private:
        Node *prev;
};
#endif

In inc/List.h

1
#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 void  sort(int) = 0;
                virtual void  swap(Node *, Node *) = 0;
                virtual Node *find(int) = 0;
 
                virtual Node *getStart() = 0;
                virtual Node *getEnd() = 0;
 
                virtual ~List();
 
        protected:
                void  setQuantity(int);
 
                virtual void  setStart(Node *) = 0;
                virtual void  setEnd  (Node *) = 0;
 
                virtual Node *setListPosition(int) = 0;
                virtual int   getListPosition(Node *) = 0;
 
        private:
                int   quantity;
};
 
#endif

tree library

In src/tree/, you will find skeletons of the above prototyped functions, hollowed out in anticipation of being made operational.

Figure out what is going on, the connections, and make sure you understand it.

Of particular focus in this project, in addition to the important tree concepts, is that of implementation. Until now we've only bothered to just get it done and working… now, not only do we care about functionality, but we look more closely at how we got there (ie the three different implementation approaches).

Reference Implementation

As the layers and complexities rise, narrowing down the source of errors becomes increasingly important.

If your tree copytree_i() isn't working, is it because of a problem with your tree? Or might it be in an underlying node operation it relies upon?

To aid you in your development efforts, you now have the ability to import functioning node, list, and stack implementations into your project for the purposes of testing your tree functionality.

This also provides another opportunity for those who have fallen behind to stay current, as they can work on this project without having needed to successfully get full node or stack (and by extension- list) functionality.

Using the test reference implementation

You'll notice that, upon running make help in the base-level Makefile, the following new options appear (about halfway in the middle):

**                                                                    **
** make use-test-reference  - use working implementation object files **
** make use-your-own-code   - use your node/list implementation code  **
**                                                                    **

In order to make use of it, you'll need to run make use-test-reference from the base of your dlt0 project directory, as follows:

lab46:~/src/data/dlt0$ make use-test-reference
...
NODE, LIST, and STACK reference implementation in place, run 'make' to build everything.
lab46:~/src/data/dlt0$ 

You'll see that final message indicating everything is in place (it automatically runs a make clean for you), and then you can go ahead and build everything with it:

lab46:~/src/data/dlt0$ make
...

Debugging: When using the test reference implementation, you will not be able to debug the contents of the node, list, and stack functions (the files provided do not have debugging symbols added), so you'll need to take care not to step into these functions (it would be just like stepping into printf(). You can still compile the project with debugging support and debug (as usual) those compiled functions (ie the stack functions).

Reverting back to using your code

If you were trying out the reference implementation to verify tree functionality, and wanted to revert back to your own code, it is as simple as:

lab46:~/src/data/dlt0$ make use-your-own-code
Local node/list/stack implementation restored, run 'make clean; make' to build everything.
lab46:~/src/data/dlt0$ 

Node Library unit tests

As a result of the addition of other, an updated set of unit tests will be released (this will mean a different number of total tests for list than previously).

Be sure to run the various node unit tests and verification scripts to see which functions have fallen out of compliance with the node struct specification changes issued in this project. The verify-node.sh script can be especially useful in getting a big picture view of what work is needed.

Tree library unit tests

In testing/tree/unit/, you will eventually find these files:

  • unit-addnode.c - unit test for the various addnode() library function
  • unit-searchtree.c - unit test for the various searchtree() library function
  • unit-grab.c - unit test for grabnode_*() library functions
  • unit-set_mode.c - unit test for set_mode() library function
  • unit-balance.c - unit test for balance() library function
  • unit-treeops.c - unit test for {mk,rm}tree library functions
  • unit-traverse.c - unit test for traverse_*() library functions
  • unit-print.c - unit test for displaying tree structure

NOTE: At the time of project release, unit tests are not yet available; so they will be released as they are developed.

There are also corresponding verify-FUNCTION.sh scripts that will output a “MATCH”/“MISMATCH” to confirm overall conformance with the pertinent tree functionality.

These are complete runnable programs (when compiled, and linked against the tree library, which is all handled for you by the Makefile system in place).

Of particular importance, I want you to take a close look at:

  • the source code to each of these unit tests
    • the purpose of these programs is to validate the correct functionality of the respective library functions
    • follow the logic
    • make sure you understand what is going on
    • ask questions to get clarification!
  • the output from these programs once compiled and ran
    • analyze the output
    • make sure you understand what is going on
    • ask questions to get clarification!

Expected Results

To assist you in verifying a correct implementation, a fully working implementation of the node and tree libraries should resemble the following (when running the respective verify script):

node library

Here is what you should get for node:

lab46:~/src/data/dlt0$ bin/verify-node.sh 
====================================================
=    Verifying Doubly-Linked Node Functionality    =
====================================================
  [mknode] Total:   6, Matches:   6, Mismatches:   0
  [cpnode] Total:   8, Matches:   8, Mismatches:   0
  [rmnode] Total:   2, Matches:   2, Mismatches:   0
====================================================
 [RESULTS] Total:  16, Matches:  16, Mismatches:   0
====================================================
lab46:~/src/data/dlt0$ 

With the addition of the other pointer, we have a few additional combinations to test.

tree library

Here is what you should get for tree:

lab46:~/src/data/dlt0$ bin/verify-tree.sh 
coming soon
lab46:~/src/data/dlt0$ 

Submission Criteria

To be successful in this project, the following criteria must be met:

  • Project must be submit on time, by the posted deadline.
    • As this project is due at the very end of the semester, there is no late window. It is either submitted, or it is not.
  • All code must compile cleanly (no warnings or errors)
    • all requested functions must be implemented in the related library
    • all requested functionality must conform to stated requirements (either on this project page or in comment banner in source code files themselves).
  • Executed programs must display in a manner similar to provided output
    • output formatted, where applicable, must match that of project requirements
  • Processing must be correct based on input given and output requested
  • Output, if applicable, must be correct based on values input
  • Code must be nicely and consistently indented (you may use the indent tool)
  • Code must be commented
    • Any “to be implemented” comments MUST be removed
      • these “to be implemented” comments, if still present at evaluation time, will result in points being deducted.
    • Sufficient comments explaining the point of provided logic MUST be present
  • Track/version the source code in a repository
  • Submit a copy of your source code to me using the submit tool (make submit will do this) by the deadline.
haas/fall2014/data/projects/eoce0.1417343716.txt.gz · Last modified: 2014/11/30 10:35 by wedge