#ifndef LIST_H
#define LIST_H
#include <string>
#include <fstream>
typedef std::string String;
template <class T>
struct Node {
T data;
Node *mNext;
};
template <typename T>
class List
{
public:
//Default constructor
List();
//Copy constructor
List(const List& copy);
//Overloaded assignment operator
List &operator=(const List& rhs);
//Destructor
~List();
//Methods
void PushFront(const T& T);
void PushBack(const T& T);
void PopFront() throw(String);
void PopBack();
T &Front() const;
T &Back() const;
void Purge();
bool empty();
int getNumberOfNodes();
Node<T>* CreateNode(const T&);
void Save(std::ofstream & file);
void Load(std::ifstream & file);
T &GetIthElement(int index) throw(int);
void Display();
private:
//Data members
Node<T>* mHead;
Node<T>* mTail;
int mNumberOfNodes;
static int mNodes;
};
#endif
template <typename T>
List<T>::List()
:mHead(nullptr), mNumberOfNodes(0)
{
}
template <typename T>
List<T>::List(const List<T> & copy)
:mHead(nullptr), mNumberOfNodes(0)
{
*this = copy;
}
template <typename T>
List<T> &List<T>::operator=(const List<T> & rhs)
{
//Check for self-assignment
if(this != &rhs)
{
//Deallocate previously allocated memory
Purge();
Node<T> * travel = rhs.mHead;
//Deep copy
while(travel != nullptr)
{
this->PushFront(this->CreateNode(travel->getData()));
travel = travel->mNext;
}
}
//Return invoking object
return *this;
}
template <typename T>
List<T>::~List()
{
Node<T> * trail = nullptr;
while(mHead != nullptr)
{
trail = mHead->mNext;
delete mHead;
mHead = trail;
}
}
template <typename T>
void List<T>::PushFront(const T& T)
{
newNode->mNext = mHead;
mHead = newNode;
//Increase number of nodes
mNumberOfNodes++;
}
template <typename T>
void List<T>::PushBack(const T& T)
{
Node<T> * travel = nullptr;
//Check to see if the list is empty
if(mHead == '\0')
mHead = newNode;
else
{
travel = mHead;
//Get to the end of the list
while(travel->mNext != '\0')
travel = travel->mNext;
//Append new node
travel->mNext = newNode;
//Increase number of nodes
mNumberOfNodes++;
}
}
template <typename T>
void List<T>::PopFront()
{
Node<T> * headPointer = nullptr;
if(mHead == nullptr)
throw "\nEmpty List!\n";
else
{
headPointer = mHead->mNext;
delete mHead;
mHead = headPointer;
mNumberOfNodes--;
}
}
template <typename T>
void List<T>::PopBack()
{
Node<T> * travel = nullptr;
Node<T> * trail = nullptr;
//Check to see if the list is empty
if(mHead == '\0')
std::cout << "\nCannot delete an empty list! " << std::endl;
else
{
travel = mHead;
//Get to the end of the list
while(travel->mNext != '\0')
{
trail = travel;
travel = travel->mNext;
}
//Delete last node
delete travel;
//Make new last node equal to null
trail->mNext = nullptr;
}
//Decrease number of Nodes
mNumberOfNodes--;
}
//const Potion &List::Front() const
template <typename T>
T &List<T>::Front() const
{
Node<T> * headPointer = nullptr;
if ( this->mHead != nullptr )
headPointer = this->mHead;
else
throw "\nEmpty list! ";
return headPointer->getData();
}
template <typename T>
T &List<T>::Back() const
{
Node<T> * travel = this->mHead;
if ( travel != nullptr )
{
while ( travel->mNext != nullptr )
travel = travel->mNext;
}
else
throw "\nEmpty list! ";
return travel->getData();
}
template <typename T>
void List<T>::Purge()
{
Node<T> * travel = mHead;
Node<T> * trail = nullptr;
while(travel != nullptr)
{
trail = travel;
travel = travel->mNext;
delete trail;
}
mHead = nullptr;
//Decrease number of nodes
mNumberOfNodes--;
}
template <typename T>
int List<T>::getNumberOfNodes()
{
return mNumberOfNodes;
}
template <typename T>
Node<T> * List<T>::CreateNode(const T & T)
{
//Allocate space for new node
Node<T> * newNode = new Node;
//Assign data to new node
newNode->mData = T;
//newNode->mData.setName(potion.getName());
//newNode->mData.setDescription(potion.getDescription());
//newNode->mData.setPotency(potion.getPotency());
//newNode->mData.setCost(potion.getCost());
//Assign new node's next
newNode->mNext = nullptr;
//Increase number of nodes
mNumberOfNodes++;
return newNode;
}
template <typename T>
bool List<T>::empty()
{
if(mNumberOfNodes == 0)
return true;
else
return false;
}
template <typename T>
void List<T>::Save(std::ofstream & file)
{
//Write the number of nodes
file.write(reinterpret_cast<char *>(&mNumberOfNodes), sizeof(int));
Node<T> * travel = this->mHead;
while( travel != nullptr )
{
travel->getData().Save(file);
travel = travel->mNext;
}
}
template <typename T>
void List<T>::Load(std::ifstream & file)
{
//Read the number of elements
file.read(reinterpret_cast<char *>(&mNumberOfNodes), sizeof(int));
//Insert nodes into list
T temp;
for( int i = 0; i < mNumberOfNodes; i++ )
{
temp.Load(file);
this->PushFront(CreateNode(temp));
mNumberOfNodes--;
mNumberOfNodes--;
}
}
template <typename T>
T &List<T>::GetIthElement(int index)
{
Node<T> * trail = this->mHead;
if(index > mNodes)
throw 666;
else
{
for(int i = 0; i < index; i++)
trail = trail->mNext;
}
return trail->getData();
}
template <typename T>
void List<T>::Display()
{
Node<T>* travel = mHead;
int i = 0;
while(travel != nullptr)
{
this->GetIthElement(i).Display();
NewLine();
travel = travel->mNext;
i++;
}
}
template <typename T>
int List<T>::mNodes = 2;