Question: Objective This assignment will provide practice with a doubly-linked list, along with practice on the basic concept of an iterator over a container. Task In
Objective
This assignment will provide practice with a doubly-linked list, along with practice on the basic concept of an iterator over a container.
Task
In your prior course, you probably saw an example of a singly-linked list. Here is a simple example of such a container, implemented as a template class:
Singly-Linked List class example
For this assignment you will implement a templated doubly-linked list class, along with an associated iterator class for helping with generic list traversals. In a doubly-linked list, each node has a pointer to the next node AND a pointer to the previous node. The following starter files are provided for you:
tnode.h -- fully defines a templated node class for use in a doubly-linked list. Note that the member data includes a data element, as well as pointers to the next and previous nodes.
tlist.h -- provides the declarations of the template classes TList (the linked list class) and TListIterator (an associated class to help with list traversal).
driver.cpp -- contains some sample test calls to the linked list, but should not be considered a complete or thorough set of tests. You will need to create more test cases to fully test your class features. This driver is provided to help illustrate some of the basic class features and concepts, including the use of iterators.
driver_output.txt -- contains the output from running the above sample driver program
Your job will be to finish this templated set of classes by defining each of the functions in the TList and TListIterator classes. These should be defined in a file called:
tlist.hpp
Note that there is already a #include at the bottom of tlist.h where your definition file will be brought in. This illustrates a pretty standard format for setting up a templated class. Note also that you should not #include your tlist.h file inside of the tlist.hpp file, because the latter is already included into the former -- you don't want to create circular and infinite #includes!
Iterators
The small class called TListIterator is a helper class that can be used in conjunction with the linked list class. This is a common feature used in container classes like this. The purpose of an iterator is to provide a common and non-implementation-specific way of traversing a container, so that mulitple containers could potentially use common algorithms (like sorting and searching functions, for example). This will be explored more in the course. For the iterator class in this assignment, here is a brief sample use:
// suppose that L is a linked list storing ints, and it has // already been populated with the values 3, 6, 9, 12, 15, 18, 21 // this call would retrieve a list iterator over the container L TListIteratoritr = L.GetIterator(); // at this point, itr currently is positioned at the first element in // the list (the 3). int x = itr.GetValue(); // x would now store 3 itr.Next(); // itr has advanced to the 6 int y = itr.GetValue(); // y would now store 6 itr.Next(); itr.Next(); // we have now advanced to the 12 int z = itr.GetValue(); // z now stores 12 itr.Previous(); // now we have moved backwards, to the 9 int a = itr.GetValue(); // a stores 9. etc.
This class essentially helps us walk through the linked list in a fairly easy way, with calls to Next() and Previous() to move around.
Program Details
Here are general descriptions of the two classes you are to define, along with a general description of each function's task.
1) class TList
The member data of this class consists of pointers to the first and last nodes, a size variable, and a dummy variable of type T that can be used for error-checking situations. Specifically, some of the functions specify to return a stored data item, but if you encounter a situation like an empty list or other situation where there would not BE a valid data item, you can return a reference to the dummy object instead. This is needed because some such functions are pass-by-reference (so that the retrieved item can be modified by the caller under normal situations).
Function descriptions
Default constructor -- creates an empty linked list
TList(T val, int num) -- creates a linked list containing "num" copies of the data element "val"
Clear -- clear out the list, resetting it to an empty list
Big Five
Destructor -- appropriate clean-up of list, no memory leaks
Copy constructor -- deep copy
Copy assignment operator -- deep copy
Move constructor -- constructor with standard move semantics
Move assignment operator -- assignment with standard move semantics
Accessors
IsEmpty -- returns true if the list is empty, false otherwise
GetSize -- returns the size (number of data elements) in the list
GetFirst -- returns the data element in the first node (by reference)
GetLast -- returns the data element in the last node (by reference)
Note that error situations in the last two functions would occur if the list was empty (this what the "dummy" item is for). Endpoint insert/removes
InsertFront -- insert the data (parameter) as the first node in the list
InsertBack -- insert the data (parameter) as the last node in the list
RemoveFront -- remove the first element in the list. If the list is empty, just leave it empty
RemoveBack -- remove the last element in the list. If the list is empty, just leave it empty
Iterator retrieval
GetIterator -- create and return an iterator that is positioned on the first node in the list. If list is empty, return default iterator
GetIteratorEnd -- create and return an iterator that is positioned on the last node in the list. If list is empty, return default iterator
Insert (2 parameters) The new data element (second parameter) should be inserted into the linked list just before the position given by the iterator (the first parameter). If the list is empty, just insert the single item. If the iterator doesn't refer to a node, insert the item at the end of the list.
Remove (1 parameter) This function should remove the data item that is given by the iterator (the parameter). The function should return an iterator to the node that is after the one that was just deleted. If the initial list was empty, there's nothing to delete -- so just leave it empty and return a default iterator.
Print Should print the entire list contents, front to back, separated by the delimiter given in the second parameter. This function may assume that the stored type T has an available insertion << operator available for printing. Print to the stream given in the first parameter.
operator+ This is a standalone function that should return a TList object that is the result of concatenating two TList objects together -- in parameter order. See driver.cpp program for examples.
2) class TListIterator
The TListIterator class has only one member data variable -- a pointer to the Node to which it currently refers (we'll call this the current node in the function descriptions below).
Default constructor -- a default iterator should just store the nunll pointer internally.
HasNext -- returns true if there is another node after the current node, false otherwise
HasPrevious -- returns true if there is another node before the current node, false otherwise
Next -- advances the iterator to the next node after the current one. Returns an iterator to the new position.
Previous -- moves the iterator to the previous node (before the current one). Returns an iterator to the new position.
GetData -- return the data item at the current node. If the iterator is not pointing to a node (i.e. null pointer), you can use the "dummy" that was defined previously. Note that this is a return by reference.
Define all of the functions for these two classes in the file tlist.hpp
3) Test Program
Create a test program of your own in the file mydriver.cpp. You can use my provided driver.cpp as a general model of how to populate a linked list. Your test program should contain the following tests/illustrations at a minimum:
Tests of all of the functions
Tests that involve Linked Lists of at least two different stored types. Suggested types: int, double, char, string
At least 10 tests of each of the following
InsertFront
InsertBack
RemoveFront
RemoveBack
Insert (iterator-based)
Remove (iterator-based)
The tests for each of these should not be all in a row for any single one. I.e. for best testing, make sure that insert/remove calls of a single function type are frequently interspersed between other types. (This way, a mistake in one will often be revealed by later calls to others)
Clear illustrations of list contents with Print before and after major sets of insert/delete tests. Make your outputs readable and easy to follow for best testing/results.
At least one test that uses an iterator to traverse the list front to back
At least one test that uses an iterator to traverse the list back to front
4) makefile
Create a makefile that configures a build of both my provided driver (driver.cpp) and your test program (mydriver.cpp). i.e. when you type "make" in the directory, it should compile and build both executables. Make your executables named "driver.x" and "mydriver.x", respectively.
5) General Requirements
Document your code appropriately so that it is readable and easy to navigate
You may use standard C++ I/O libraries, as well as class libraries like string. You may NOT use any of the container class libraries from the STL
If you wish to add any helper functions to the TList class, you may modify the tlist.h file for this purpose. But do NOT change any of the expected interface function prototypes or add extra member data. Any helper functions you write should be in the private section
Make sure your files compile and run on linprog.cs.fsu.edu with g++, using the C++11 standard compilation flag. This is where they will be tested and graded
------------------------------------------------------tnode.h----------------------------------------------------------------------------------
// Starter file for doubly-linked list. templated Node class // each Node stores a piece of data, along with prev and next pointers // to point to the previous and the next nodes in the list, respectively #includetemplate class TList; // forward declaration template class TListIterator; // forward declaration // declaration of Node class template class Node { friend class TList ; friend class TListIterator ; public: Node(const T& d); Node(T && d); private: T data; // data element to store Node * prev; // pointer to previous node Node * next; // pointer to next node }; // Node constructor definitions template Node ::Node(const T& d) // copy version { data = d; // set data prev = next = nullptr; // null pointers to start } template Node ::Node(T && d) // MOVE version (if applicable for type T) { data = std::move(d); // set data prev = next = nullptr; // null pointers to start }
--------------------------------------------------------tlist.h --------------------------------------------------------------------
#include#include #include "tnode.h" // Declaration of class TList template class TList { friend class TListIterator ; public: TList(); // create empty linked list TList(T val, int num); // create list with num copies of val ~TList(); // destructor TList(const TList& L); // copy constructor TList& operator=(const TList& L); // copy assignment operator TList(TList && L); // move constructor TList& operator=(TList && L); // move assignment operator bool IsEmpty() const; // checks to see whether list is empty void Clear(); // clear out list, reset to empty int GetSize() const; // return the size of the list void InsertFront(const T& d); // insert data d as first element void InsertBack(const T& d); // insert data d as last element void RemoveFront(); // remove first element of list void RemoveBack(); // remove last element of list T& GetFirst() const; // return first element of list T& GetLast() const; // return last element of list TListIterator GetIterator() const; // return iterator to first item TListIterator GetIteratorEnd() const; // return iterator to last item // insert data element d just before item at pos position void Insert(TListIterator pos, const T& d); // remove data item at position pos. Return iterator to the item // that comes after the one being deleted TListIterator Remove(TListIterator pos); // print list contents in order, separated by given delimiter void Print(std::ostream& os, char delim = ' ') const; private: Node * first; // pointer to first node in list Node * last; // pointer to last node in list int size; // number of nodes in the list static T dummy; // dummy object, for empty list data returns // assuming type T has default construction }; template T TList ::dummy; // initialization of static member // stand-alone function for concatenating two TList objects template TList operator+(const TList & t1, const TList & t2); // Declaration of class TListIterator template class TListIterator { friend class TList ; public: TListIterator(); // default constructor bool HasNext() const; // next item available? bool HasPrevious() const; // previous item available? TListIterator Next(); // advance to next item TListIterator Previous(); // move to previous item T& GetData() const; // return data element of current node private: Node * ptr; // pointer to current list item }; #include "tlist.hpp" // bring in definition file here
-------------------------------------------------------------driver.cpp-------------------------------------------------------------------------
#include#include #include "tlist.h" using namespace std; template void PrintList(const TList & L, string label) { cout << label << " size is: " << L.GetSize() << " " << label << " = "; L.Print(cout); cout << " "; } int main() { TList L1; // integer list for (int i = 0; i < 10; i++) L1.InsertBack(i*2); PrintList(L1, "L1"); for (int i = 0; i < 8; i++) L1.InsertFront( (i+1) * 100 ); PrintList(L1, "L1"); L1.RemoveBack(); PrintList(L1, "L1"); L1.RemoveBack(); PrintList(L1, "L1"); L1.RemoveFront(); PrintList(L1, "L1"); L1.RemoveFront(); PrintList(L1, "L1"); // try an iterator, and some middle inserts/deletes cout << "Testing some inserts with an iterator "; TListIterator itr = L1.GetIterator(); L1.Insert(itr, 999); itr.Next(); itr.Next(); // advance two spots L1.Insert(itr, 888); itr.Next(); itr.Next(); itr.Next(); // advance three spots L1.Insert(itr, 777); PrintList(L1, "L1"); cout << "Testing some removes (with iterator) "; itr.Next(); itr.Next(); // advance two spots itr = L1.Remove(itr); // delete current item PrintList(L1, "L1"); for (int i = 0; i < 5; i++) itr.Previous(); // back 5 spots itr = L1.Remove(itr); // delete current item PrintList(L1, "L1"); // building another list TList L2; for (int i = 0; i < 10; i++) L2.InsertBack(i * 3 + 1); PrintList(L2, "L2"); // Testing + overload: TList L3 = L1 + TList (100, 7); TList L4; L4 = L2 + L1; PrintList(L3, "L3"); PrintList(L4, "L4"); }
-------------------------------------------------------------driver.output---------------------------------------------------------------------
L1 size is: 10 L1 = 0 2 4 6 8 10 12 14 16 18 L1 size is: 18 L1 = 800 700 600 500 400 300 200 100 0 2 4 6 8 10 12 14 16 18 L1 size is: 17 L1 = 800 700 600 500 400 300 200 100 0 2 4 6 8 10 12 14 16 L1 size is: 16 L1 = 800 700 600 500 400 300 200 100 0 2 4 6 8 10 12 14 L1 size is: 15 L1 = 700 600 500 400 300 200 100 0 2 4 6 8 10 12 14 L1 size is: 14 L1 = 600 500 400 300 200 100 0 2 4 6 8 10 12 14 Testing some inserts with an iterator L1 size is: 17 L1 = 999 600 500 888 400 300 200 777 100 0 2 4 6 8 10 12 14 Testing some removes (with iterator) L1 size is: 16 L1 = 999 600 500 888 400 300 200 777 100 0 4 6 8 10 12 14 L1 size is: 15 L1 = 999 600 500 888 400 200 777 100 0 4 6 8 10 12 14 L2 size is: 10 L2 = 1 4 7 10 13 16 19 22 25 28 L3 size is: 22 L3 = 999 600 500 888 400 200 777 100 0 4 6 8 10 12 14 100 100 100 100 100 100 100 L4 size is: 25 L4 = 1 4 7 10 13 16 19 22 25 28 999 600 500 888 400 200 777 100 0 4 6 8 10 12 14
-------------------------------------------tlist.hpp---------------------------------------------------------------------------------------------- *******this is what i have completed so far. I am stuck on the cout overload for both print functions ****************
#include
//*****************************************************************// // ------ defintion os stream ------- // //*****************************************************************// template
//*****************************************************************// // ------ defintion TListIterator ------- // //*****************************************************************// template
template
template
template
template
}
template
template
//*****************************************************************// // ------ defintion TList ------- // //*****************************************************************// /*template
}*/
template
template
template
/*TList(const TList& L); // copy constructor TList& operator=(const TList& L); // copy assignment operator TList(TList && L); // move constructor TList& operator=(TList && L); // move assignment operator */
template
template
template
template
template
template
template
/* T& GetFirst() const; // return first element of list T& GetLast() const; // return last element of list TListIterator
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
