Copy Constructor for Circular Singly Linked List - c++

So I have been coding in C++ for not so long and am struggling with a copy constructor and my program keeps on crashing when I use it.
Node:
template <class T>
class Node
{
public:
Node(T data, Node<T> * n = 0)
{ element = data;
next = n;
prev = n;}
~Node()
{ next = 0;
prev = 0;}
T element;
Node<T>* next;
Node<T>* prev;
Function Code:
CircularList<T>::CircularList(const CircularList<T> & other)
{
if(other.tail == NULL)
{
this->tail = NULL;
}
else
{
this->tail = other.tail;
Node<T> * original = this->tail;
Node<T> * temp = other.tail->next;
while(temp != other.tail)
{
original->next = temp;
temp = temp->next;
original = original->next;
}
original->next = temp;
}
}
(EDIT)
Here is the specification for the CircularList Class. I think I just do not understand what steps to take to make it deep copy rather than shallow copy.
template<class T>
class CircularList;
template<class T>
ostream& operator<<(ostream&,CircularList<T>&);
template<class T>
class CircularList : public LinearStructure<T>
{
public:
friend ostream& operator<< <T>(ostream&,CircularList<T>&);
CircularList();
CircularList(const CircularList<T>& other);
CircularList<T>& operator=(const CircularList<T>& other);
virtual CircularList<T>* clone();
virtual ~CircularList();
virtual void insert(int index, T element);
virtual T remove(int index);
virtual T get(int index) const;
virtual bool isEmpty();
virtual void clear();
Node<T>* getLeader();
protected:
ostream& print(ostream& os);
private:
int size() const;
Node<T>* tail;
};
So yeah when I test it with this (the list isn't empty):
CircularList<int> clist;
clist.insert(0,8);
CircularList<int> clist2(clist);
It crashes. Any help would be appreciated!!

Related

How to properly use template class with an abstract pointer type

I created a List with a template Node class to hold different data types such as Node<int> but also more complex types such as Node<BaseEvent*>.
I also have an event container class to hold different event objects so it has a member argument
List<BaseEvent*> events;
where BaseEvent is an abstract class with derived classes that are not abstract.
In the event container I have a method called "add" (see below) that adds a new event to that events.
BaseEvent* eventClone = event.clone();
The clone returns a pointer to a new derived object such as:
new OpenEvent(*this);
Once it calls the list's insert method, it instantiates a new Node (see below), and in the Node constructor it assigns the value like so:
value(new T(new_value))
So basically it allocates a pointer memory (T=BaseEvent*).
I think I might be losing the eventClone pointer and have a memory leak.
The problem is that when I debugged it I saw that both: T* value; (aka BaseEvent** value) and BaseEvent* eventClone have the same address in memory.
I'm not sure if when I do delete value in the destructor of Node it will just free the pointer allocation to BaseEvent* or also the data that it holds.
Any insights are welcome!
Relevant code snippets
Node<T>
template <class T>
class Node
{
public:
Node(const T& new_value, Node* new_next = NULL, Node* new_prev = NULL);
~Node();
const T& getValue() const;
Node<T>* getNext() const;
Node<T>* getPrev() const;
void setNext(Node* node);
void setPrev(Node* node);
private:
T* value;
Node* next;
Node* prev;
};
template <class T>
Node<T>::Node(const T& new_value, Node* new_next, Node* new_prev) :
value(new T(new_value))
{
next = new_next;
prev = new_prev;
}
template <class T>
Node<T>::~Node()
{
delete value;
}
...
Linked list that uses Node<T>
template <class T>
class List
{
public:
List();
~List();
int getSize() const;
Node<T>* getFirst() const;
Node<T>* getNext(Node<T>& node) const;
Node<T>* getPrev(Node<T>& node) const;
void insertStart(const T& data);
void insertLast(const T& data);
void insertAfter(Node<T>& target, const T& data);
void insertBefore(Node<T>& target, const T& data);
void removeNode(Node<T>& node);
bool contains(const T data);
private:
Node<T>* head;
int size;
};
template <class T>
List<T>::List() : head(NULL), size(0)
{
}
template <class T>
List<T>::~List()
{
Node<T>* temp;
while (head)
{
temp = head;
head = head->getNext();
delete temp;
size--;
}
}
...
template <class T>
void List<T>::insertStart(const T& data) {
if (size == 0)
{
head = new Node<T>(data);
}
else
{
Node<T>* temp = new Node<T>(data, head);
head->setPrev(temp);
head = temp;
}
size++;
}
...
The event container class:
class EventContainer
{
public:
EventContainer() :
events(List<BaseEvent*>()) {}
~EventContainer() {}
virtual void add(const BaseEvent&);
class EventIterator
{
public:
EventIterator() :
current(NULL) {}
EventIterator(Node<BaseEvent*>& node) :
current(&node) {}
EventIterator(Node<BaseEvent*>* node) :
current(node) {}
~EventIterator() {}
EventIterator& operator=(const EventIterator& nodeIterator) {
current = nodeIterator.current;
return *this;
}
EventIterator& operator++() {
current = current->getNext();
return *this;
}
BaseEvent& operator*() const {
return *(current->getValue());
}
friend bool operator==(const EventIterator& iterator1, const EventIterator& iterator2) {
return iterator1.current == iterator2.current;
}
bool operator!=(const EventIterator& iterator) const {
return !(*this == iterator);
}
private:
Node<BaseEvent*>* current;
};
virtual EventIterator begin() const;
virtual EventIterator end() const;
private:
List<BaseEvent*> events;
};
The implementation of add method:
void EventContainer::add(const BaseEvent& event) {
BaseEvent* eventClone = event.clone();
if (events.getSize() == 0)
{
events.insertStart(eventClone);
return;
}
Node<BaseEvent*>* current = events.getFirst();
while (current != NULL)
{
if (*eventClone < *(current->getValue()))
{
events.insertBefore(*current, eventClone);
return;
}
current = current->getNext();
}
events.insertLast(eventClone);
}
EventContainer::EventIterator EventContainer::begin() const {
return events.getFirst();
}
EventContainer::EventIterator EventContainer::end() const {
return NULL;
}

How can I add an already created node to a linked list?

I'm trying to add an already created node to a linked list by passing a pointer to pointer as argument. I can't figure out how to make it work.
void List::add(Node* n, int pos){
if(pos > size)
pos = size;
if(pos == 0){
if (head == NULL){
head = n;
}
else{
Node* temp = head;
n->setNext(temp);
head = n;
}
}
else{
Node* temp = head;
int currPos = 0;
while(temp->getNext() != NULL && currPos != pos){
temp = temp->getNext();
currPos++;
}
if(currPos == pos){
Node* next = temp->getNext();
n->setNext(next);
}
temp->setNext(n);
}
size++;
}
I implemented a method that creates a new node for each call and it works fine, but I need to work with already created nodes.
Below you have the header files for List and Node.
#pragma once
#include "Node.hpp"
#include <iostream>
class List{
Node* head;
int size;
public:
List();
List(const Team&, Node* = NULL);
// List(const List&);
// List& operator=(const List&);
~List();
void add(const Team&, int = 0);
void add(Node*, int = 0);
void remove(const Team&);
void removeLowest(int unqualNum);
void print() const;
void printNames(ostream& o = cout) const;
int getSize() const;
Node* getHead() const;
};
#pragma once
#include "Team.hpp"
class Node{
Team value;
Node* next;
public:
Node(const Team& = Team(), Node* = NULL);
// Node(const Node&);
// operator=(const Node&);
// ~Node();
Team getValue() const;
void setValue(const Team&);
Node* getNext() const;
void setNext(Node*);
};
I have another class Stack where I want to use the method.
#pragma once
#include "Node.hpp"
#include "List.hpp"
#include <iostream>
class Stack{
Node* head;
int size;
public:
Stack();
Stack(const Team&, Node* = NULL);
// Stack(const Stack&);
// Stack& operator=(const Stack&);
~Stack();
void push(const Team&);
void pop();
void print(ostream& = cout) const;
int getSize() const;
Node* getHead() const;
void toList(List* );
};
In method toList, I try to move all the nodes of the stack to a list passed as argument.
void Stack::toList(List* l){
Node *temp = head;
while(temp){
l->add(temp->getValue(), l->getSize()); // This works similar add method that build node inside
l->add(temp, l->getSize()); // This doesn't, the method with Node as parameter
temp = temp->getNext();
}
}

Why do I get compile errors when I try to make this constructor generic?

So I have these three classes made
template <class dataType>
class listEntry
{
private:
dataType data;
public:
listEntry *next;
listEntry *prev;
dataType getData() { return this->data; }
listEntry();
listEntry(dataType data) { this->data = data; }
~listEntry() {};
};
template <class dataType>
class List
{
private:
dataType *head;
dataType *tail;
int count;
public:
dataType *getHead() { return this->head; }
dataType *getTail() { return this->tail; }
void addToTail(dataType *newEntry);
void addToHead(dataType *newEntry);
int getCount() { return count; }
void printListForward();
List();
List(const List<dataType> &li);
~List();
};
template <class dataType>
class Queue: public List<dataType>
{
public:
void enQueue(dataType *newEntry);
Queue():List<dataType>() { return; }
Queue(const List<dataType>& li):List<dataType>(li) { return; }
Queue(dataType data);
Queue(listEntry<dataType> le);
}
And one of my constructors for the Queue is this:
template <class dataType>
Queue<dataType>::Queue(dataType data)
{
enQueue(new listEntry<int>(data));
}
However, I want enQueue(new listEntry<int>(data)); to be enQueue(new listEntry<dataType>(data)); so that it is generic and can work with any data type. But when I change it to that, I get compile errors.
The enQueue definition looks like this:
template <class dataType>
void Queue<dataType>::enQueue(dataType *newEntry)
{
this->addToTail(newEntry);
}
How come writing dataType instead of int gets compile errors?
There are some design issues with your code:
The head and tail members of List need to be declared as listEntry<dataType>* instead of as dataType*.
addToTail(), addToHead() and enQueue() should all take dataType values instead of dataType* pointers.
addToTail() and addToHead() need to create a new listEntry<dataType> object internally.
Try something more like this instead:
template <class dataType>
class listEntry
{
private:
dataType data;
public:
listEntry *prev;
listEntry *next;
dataType getData() const { return data; }
listEntry(const dataType &data, listEntry *prev = NULL, listEntry *next = NULL);
};
template <class dataType>
class List
{
public:
typedef listEntry<dataType> entryType;
private:
entryType *head;
entryType *tail;
int count;
public:
entryType* getHead() { return head; }
const entryType* getHead() const { return head; }
entryType* getTail() { return tail; }
const entryType* getTail() const { return tail; }
void addToTail(const dataType &data);
void addToHead(const dataType &data);
int getCount() const { return count; }
void printListForward() const;
List();
List(const List &li);
~List();
List& operator=(const List &li);
};
template <class dataType>
class Queue : public List<dataType>
{
public:
typedef List<dataType> listType;
void enQueue(const dataType &data);
Queue() {}
Queue(const Queue &q) : listType(q) {}
Queue(const listType &li) : listType(li) {}
Queue(const dataType &data);
};
...
template<class dataType>
listEntry<dataType>::listEntry(const dataType &data, listEntry *prev, listEntry *next)
: data(data), prev(prev), next(next)
{
}
template<class dataType>
void List<dataType>::addToTail(const dataType &data)
{
entryType *newEntry = new entryType(data, tail);
if (!head) head = newEntry;
if (tail) tail->next = newEntry;
tail = newEntry;
++count;
}
template<class dataType>
void List<dataType>::addToHead(const dataType &data)
{
entryType *newEntry = new entryType(data, NULL, head);
if (!tail) tail = newEntry;
if (head) head->prev = newEntry;
head = newEntry;
++count;
}
template<class dataType>
void List<dataType>::printListForward() const
{
entryType *entry = head;
while (entry)
{
//...
entry = entry->next;
}
}
template<class dataType>
void List<dataType>::List()
: head(NULL), tail(NULL), count(0)
{
}
template<class dataType>
void List<dataType>::List(const List<dataType> &li)
: head(NULL), tail(NULL), count(0)
{
const entryType *entry = li.getHead();
while (entry)
{
addToTail(entry->getData());
entry = entry->next;
}
}
template<class dataType>
void List<dataType>::~List()
{
entryType *entry = head;
while (entry)
{
entryType *next = entry->next;
delete entry;
entry = next;
}
}
template<class dataType>
List<dataType>& List<dataType>::operator=(const List<dataType> &li)
{
if (&li != this)
{
List<dataType> temp(li);
std::swap(head, temp.head);
std::swap(tail, temp.tail);
std::swap(count, temp.count);
}
return *this;
}
template <class dataType>
Queue<dataType>::Queue(const dataType &data)
{
enQueue(data);
}
template <class dataType>
void Queue<dataType>::enQueue(const dataType &data)
{
addToTail(data);
}
Then you can do things like this:
Queue<int> q;
q.enQueue(12345);
q.enQueue(67890);
q.printListForward();

Linked List ostream overload weird values

I'm realitively new to using linked lists. I'm trying to overload the ostream opperator for a doubly linked list with decleration :
template <class T>
class DynamicList;
template <class T>
template <class T>
class DynamicList
{
private:
Node<T> *head;
public:
class Node
{
public:
T* value;
Node<T> *next;
Node<T> *prev;
Node(T val)
{
next = nullptr;
prev = nullptr;
value = &val;
}
};
DynamicList();
~DynamicList();
void operator+=(const T);
friend std::ostream & operator<< <>(std::ostream &, const DynamicList<T> &);
};
and function defenition:
template <class T>
ostream& operator << (ostream & out , const DynamicList<T> & rhs)
{
Node<T>* nodePtr = rhs.head;
Node<T>* nptr = nodePtr->next;
while(nodePtr != NULL)
{
cout<<*(nodePtr->value)<<" ";
nodePtr = nodePtr->next;
}
out<<endl;
return out;
}
template <class T>
void DynamicList<T>:: operator +=(const T val)
{
Node<T>* nodePtr = nullptr;
T vall = val;
Node<T>* newNode = new Node<T>(vall);
if(!head)
{
head = newNode;
}
else
{
nodePtr = head;
while((nodePtr->next))
{
nodePtr = nodePtr->next;
}
nodePtr->next = newNode;
newNode->prev = nodePtr;
}
Every time I'm calling the opperator it gives a weird output for example using:
for(int i = 1; i <= 3; i++)
{
list += i;
}
cout<<list;
It would give an output like 135727363 135727383 135727383 ,I'd just like to know what I'm doing wrong and possibly how I could solve it
Your problem is here:
T* value;
You are storing the address of a value.
The problem is that you are storing the address of a variable that has gone out of scope.
T vall = val;
Node<T>* newNode = new Node<T>(vall);
The variable vall is local to the function operator += which means after it exists it no longer exists (and can contain anything).
To fix change the node to store the value.
class Node
{
public:
T value; // Notice no star here.
Node<T> *next;
Node<T> *prev;
Node(T const& val) // Add `const&` here to avoid a copy.
{
next = nullptr;
prev = nullptr;
value = val; // Notice no and `&` here
}
};

C++ Insert integer nodes into a templated singly linked list class in ascending order - Homework

I'm been having trouble with either my constructor or my insert function, I'm not sure which is the issue, but the real issue is that I get the error code mentioning I'm having an error with things getting de-referenced. All I'm trying to do is insert a node containing an integer value in the correct position.
This is the declaration:
template <class T>
class LinkedList
{
template <class T>
struct Node
{
T mData;
Node<T> *mNext;
/* Pre: None
* Post: This object is initialized using default values
* Purpose: To initialize date object
*************************************************************************/
Node()
{
mData = T();
mNext = NULL;
}
/* Pre: None
* Post: This object is initialized using specified data
* Purpose: To intialize date object
*************************************************************************/
Node(T data, Node<T>* next)
{
mData = data;
mNext = next;
}
};
private:
Node<T> *mHead;
int mCount;
public:
LinkedList();
~LinkedList();
int getCount();
T getData(int index);
void setData(int index, T data);
void clear();
void display();
bool insert(T data);
bool isEmpty();
bool isExist(T searchKey);
bool remove(T searchKey);
T removeAt(int index);
T operator[](int index);
void operator=(LinkedList<T> *list);
};
And this is the insert:
template <class T>
bool LinkedList<T>::insert(T data)
{
Node<T>* current = mHead;
if (!current)
{
if (mCount == 0)
{
current->mData = data;
}
else
{
while (current->mNext != NULL)
{
if (current->mData == data)
return false;
else if (current->mNext->mData < data)
{
Node<T>* newNode = new Node<T>();
newNode->mData = data;
newNode->mNext = current->mNext;
current->mNext = newNode;
}
current = current->mNext;
}
}
}
else
{
Node<T>* node = new Node<T>(data, NULL);
current->mNext = node;
}
mCount++;
return true;
}
Every time my program breaks, it's at this line
current->mData = data;
You shouldn't declare Node class as template, in fact you should get a compile error message like error: declaration of 'T' shadows template parameter.
Remove template<class T> from Node and change Node<T> to Node throughout the code.