Why is there a memory leak on SinglyLinkedList deletion? - c++

I have a utility library that I developed and noticed I have a memory leak in the SinglyLinkedList class. After debugging the code, I could not find why I have a memory leak. This is the test case I am using in the main function:
#include <iostream>
#include "SinglyLinkedList.h"
using namespace std;
int main() {
cout << "Program operating..." << endl;
do {
SinglyLinkedList<int> list = SinglyLinkedList<int>();
list.add(1);
list.add(1);
list.add(1);
} while (true);
cout << "Program terminated..." << endl;
}
Here is SinglyLinkedList.h file. It contains the SinglyLinkedNode and SinglyLinkedList class.
#pragma once
// SinglyLinkedNode
template <class T>
class SinglyLinkedNode {
public:
T data;
SinglyLinkedNode<T>* nextNode;
SinglyLinkedNode(T data);
SinglyLinkedNode(const SinglyLinkedNode& singlyLinkedNode);
void operator = (const SinglyLinkedNode& singlyLinkedNode);
~SinglyLinkedNode();
};
template <class T>
SinglyLinkedNode<T>::SinglyLinkedNode(T data) {
this->data = data;
nextNode = nullptr;
}
template <class T>
SinglyLinkedNode<T>::SinglyLinkedNode(const SinglyLinkedNode& singlyLinkedNode) {
this->data = singlyLinkedNode.data;
nextNode = nullptr;
}
template <class T>
void SinglyLinkedNode<T>::operator = (const SinglyLinkedNode& singlyLinkedNode) {
this->data = singlyLinkedNode.data;
nextNode = nullptr;
}
template <class T>
SinglyLinkedNode<T>::~SinglyLinkedNode() {
nextNode = nullptr;
}
// SinglyLinkedList
template <class E>
class SinglyLinkedList {
private:
unsigned int size;
public:
SinglyLinkedNode<E>* head;
SinglyLinkedNode<E>* tail;
SinglyLinkedList();
SinglyLinkedList(const SinglyLinkedList& singlyLinkedList); // O(n)
void operator = (const SinglyLinkedList<E> singlyLinkedList); // O(n)
SinglyLinkedNode<E>* add(E data); // O(1)
SinglyLinkedNode<E>* addAt(unsigned int i, E data); // O(n)
SinglyLinkedNode<E>* addToHead(E data); // O(1)
SinglyLinkedNode<E>* addToTail(E data); // O(n)
SinglyLinkedNode<E>* getNodeAt(unsigned int i); // O(n)
SinglyLinkedNode<E>* getHeadNode(); // O(1)
SinglyLinkedNode<E>* getTailNode(); // O(1)
bool contains(SinglyLinkedNode<E>* singlyLinkedNode); // O(n)
E getDataAt(unsigned int i); // O(n)
E getHeadData(); // O(1)
E getTailData(); // O(1)
bool contains(E data); // O(n)
E remove(E data); // O(n)
E removeAt(unsigned int i); // O(n)
E removeHead(); // O(1)
E removeTail(); // O(size)
void clear(); // O(size)
bool isEmpty(); // O(1)
unsigned int getSize(); // O(1)
~SinglyLinkedList();
};
template <class E>
SinglyLinkedList<E>::SinglyLinkedList() {
head = nullptr;
tail = nullptr;
size = 0;
}
template <class E>
SinglyLinkedList<E>::SinglyLinkedList(const SinglyLinkedList<E>& singlyLinkedList) {
head = nullptr;
tail = nullptr;
size = 0;
SinglyLinkedNode<E>* currentNode = singlyLinkedList.head;
while (currentNode != nullptr) {
addToTail(currentNode->data);
currentNode = currentNode->nextNode;
}
}
template <class E>
void SinglyLinkedList<E>::operator = (const SinglyLinkedList<E> singlyLinkedList) {
head = nullptr;
tail = nullptr;
size = 0;
SinglyLinkedNode<E>* currentNode = singlyLinkedList.head;
while (currentNode != nullptr) {
addToTail(currentNode->data);
currentNode = currentNode->nextNode;
}
}
template <class E>
SinglyLinkedNode<E>* SinglyLinkedList<E>::add(E data) {
return addToTail(data);
}
template <class E>
SinglyLinkedNode<E>* SinglyLinkedList<E>::addAt(unsigned int i, E data) {
if (i > size)
return nullptr;
SinglyLinkedNode<E>* singlyLinkedNode = new SinglyLinkedNode<E>(data);
if (size == 0) {
head = singlyLinkedNode;
tail = singlyLinkedNode;
size++;
return singlyLinkedNode;
}
if (i == 0) {
singlyLinkedNode->nextNode = head;
head = singlyLinkedNode;
size++;
return singlyLinkedNode;
}
SinglyLinkedNode<E>* currentNode = head;
for (unsigned int j = 1; j < i; j++)
currentNode = currentNode->nextNode;
singlyLinkedNode->nextNode = currentNode->nextNode;
currentNode->nextNode = singlyLinkedNode;
size++;
return singlyLinkedNode;
}
template <class E>
SinglyLinkedNode<E>* SinglyLinkedList<E>::addToHead(E data) {
SinglyLinkedNode<E>* singlyLinkedNode = new SinglyLinkedNode<E>(data);
if (size == 0) {
head = singlyLinkedNode;
tail = singlyLinkedNode;
size++;
return singlyLinkedNode;
}
singlyLinkedNode->nextNode = head;
head = singlyLinkedNode;
size++;
return singlyLinkedNode;
}
template <class E>
SinglyLinkedNode<E>* SinglyLinkedList<E>::addToTail(E data) {
SinglyLinkedNode<E>* singlyLinkedNode = new SinglyLinkedNode<E>(data);
if (size == 0) {
head = singlyLinkedNode;
tail = singlyLinkedNode;
size++;
return singlyLinkedNode;
}
tail->nextNode = new SinglyLinkedNode<E>(data);
tail = tail->nextNode;
size++;
return singlyLinkedNode;
}
template <class E>
SinglyLinkedNode<E>* SinglyLinkedList<E>::getNodeAt(unsigned int i) {
if (size == 0 || i >= size)
return nullptr;
SinglyLinkedNode<E>* currentNode = head;
for (unsigned int j = 0; j < i; j++)
currentNode = currentNode->nextNode;
return currentNode;
}
template <class E>
SinglyLinkedNode<E>* SinglyLinkedList<E>::getHeadNode() {
return head;
}
template <class E>
SinglyLinkedNode<E>* SinglyLinkedList<E>::getTailNode() {
return tail;
}
template <class E>
bool SinglyLinkedList<E>::contains(SinglyLinkedNode<E>* singlyLinkedNode) {
SinglyLinkedList<E>* currentNode = head;
while (currentNode != nullptr)
if (currentNode == singlyLinkedNode)
return true;
return false;
}
template <class E>
E SinglyLinkedList<E>::getDataAt(unsigned int i) {
SinglyLinkedNode<E>* singlyLinkedNode = getNodeAt(i);
if (singlyLinkedNode == nullptr)
throw 0;
return singlyLinkedNode->data;
}
template <class E>
E SinglyLinkedList<E>::getHeadData() {
if (head == nullptr)
throw 1;
return head->data;
}
template <class E>
E SinglyLinkedList<E>::getTailData() {
if (tail == nullptr)
throw 2;
return tail->data;
}
template <class E>
bool SinglyLinkedList<E>::contains(E data) {
if (size == 0)
return false;
SinglyLinkedNode<E>* currentNode = head;
while (currentNode != nullptr) {
if (currentNode->data == data)
return true;
currentNode = currentNode->nextNode;
}
return false;
}
template <class E>
E SinglyLinkedList<E>::remove(E data) {
if (size == 0)
throw 3;
if (head->data == data)
return removeHead();
if (size > 1) {
SinglyLinkedNode<E>* currentNode = head;
while (currentNode->nextNode != nullptr) {
if (currentNode->nextNode->data == data) {
E data = currentNode->nextNode->data;
SinglyLinkedNode<E>* nodeToDelete = currentNode->nextNode;
if (nodeToDelete == tail)
tail = currentNode;
currentNode->nextNode = currentNode->nextNode->nextNode;
delete(nodeToDelete);
size--;
return data;
}
currentNode = currentNode->nextNode;
}
}
throw 4;
}
template <class E>
E SinglyLinkedList<E>::removeAt(unsigned int i) {
if (size == 0 || i >= size)
throw 5;
if (i == 0)
return removeHead();
if (i == (size - 1))
return removeTail();
SinglyLinkedNode<E>* currentNode = head;
for (unsigned int j = 1; j < i; j++)
currentNode = currentNode->nextNode;
E data = currentNode->nextNode->data;
SinglyLinkedNode<E>* nodeToDelete = currentNode->nextNode;
currentNode->nextNode = currentNode->nextNode->nextNode;
delete(nodeToDelete);
size--;
return data;
}
template <class E>
E SinglyLinkedList<E>::removeHead() {
if (size == 0)
throw 6;
if (size == 1) {
E data = head->data;
delete(head);
size--;
head = nullptr;
tail = nullptr;
return data;
}
if (size == 2) {
E data = head->data;
SinglyLinkedNode<E>* newHead = head->nextNode;
delete(head);
head = newHead;
tail = newHead;
size--;
return data;
}
SinglyLinkedNode<E>* newHead = head->nextNode;
E data = head->data;
delete head;
head = newHead;
size--;
return data;
}
template <class E>
E SinglyLinkedList<E>::removeTail() {
if (size == 0)
throw 7;
if (size == 1)
return removeHead();
if (size == 2) {
E data = tail->data;
delete(tail);
tail = head;
size--;
return data;
}
SinglyLinkedNode<E>* currentNode = head;
while (currentNode->nextNode->nextNode != nullptr)
currentNode = currentNode->nextNode;
E data = tail->data;
delete(tail);
currentNode->nextNode = nullptr;
tail = currentNode;
size--;
return data;
}
template <class E>
void SinglyLinkedList<E>::clear() {
while (size > 0)
removeHead();
}
template <class E>
bool SinglyLinkedList<E>::isEmpty() {
if (size == 0)
return true;
}
template <class E>
unsigned int SinglyLinkedList<E>::getSize() {
return size;
}
template <class E>
SinglyLinkedList<E>::~SinglyLinkedList() {
clear();
}
The memory leak only asserts when I have more than one node in the list. I tried going step by step using the debugger, but everything seems to be working fine. Any leads would be very helpful.

At least in this function
template <class E>
SinglyLinkedNode<E>* SinglyLinkedList<E>::addToTail(E data) {
SinglyLinkedNode<E>* singlyLinkedNode = new SinglyLinkedNode<E>(data);
if (size == 0) {
head = singlyLinkedNode;
tail = singlyLinkedNode;
size++;
return singlyLinkedNode;
}
tail->nextNode = new SinglyLinkedNode<E>(data);
tail = tail->nextNode;
size++;
return singlyLinkedNode;
}
called by the function add
template <class E>
SinglyLinkedNode<E>* SinglyLinkedList<E>::add(E data) {
return addToTail(data);
}
there is a memory leak.
A new node is allocated twice when the list is not empty
SinglyLinkedNode<E>* singlyLinkedNode = new SinglyLinkedNode<E>(data);
and
tail->nextNode = new SinglyLinkedNode<E>(data);
And the allocated node pointed to by the pointer singlyLinkedNode is not deleted.
There is other problematic code in your program. For example the parameter of the assignment operator
void operator = (const SinglyLinkedList<E> singlyLinkedList);
should be a reference. Otherwise the operator will be inefficient because it will create a new temporary list.
And moreover it also produces numerous memory leaks because it does not clear the current list.
template <class E>
void SinglyLinkedList<E>::operator = (const SinglyLinkedList<E> singlyLinkedList) {
head = nullptr;
tail = nullptr;
size = 0;
SinglyLinkedNode<E>* currentNode = singlyLinkedList.head;
while (currentNode != nullptr) {
addToTail(currentNode->data);
currentNode = currentNode->nextNode;
}
}
You need to revise your entire program.:)

Related

Split linked list into half in c++

What is wrong with my code in splitting the linked list into half, what causes the error? I kinda get the logic on how to split it, but is this the right implementation?
template <typename T>
Forward_list<T> Forward_list<T>::split()
{
Forward_list<T> my_list;
Node* tmp = head_;
Node* tmp2 = head_;
if (my_list.empty() == true)
{
return *this;
}
while (tmp != nullptr)
{
tmp = tmp->next;
if (tmp == nullptr) break;
tmp = tmp->next;
tmp2 = tmp2->next;
}
my_list.head_ = tmp2->next;
tmp2->next = nullptr;
my_list.size_++;
return my_list;
}
You did not show your code. That is a pity. So, I needed to stub it.
You have 3 main errors.
Checking for the empty list is wrong. You are checking the just newly create my_list. This will of course always be empty.
The traversing of the list is wrong
The size calculation is wrong.
Please see the corrected code below:
template <typename T>
struct Forward_list {
struct Node {
T data{};
Node* next{};
};
Node* head_{};
unsigned int size_{};
Forward_list<T> split();
void push_back(const T& t);
bool empty() const { return size_ == 0; }
};
template <typename T>
void Forward_list<T>::push_back(const T& t) {
Node* data = new Node{ t,nullptr };
if (head_ == nullptr)
head_ = data;
else {
Node* tmp{ head_ };
while (tmp->next)
tmp = tmp->next;
tmp->next = data;
}
++size_;
}
template <typename T>
Forward_list<T> Forward_list<T>::split()
{
Forward_list<T> my_list;
Node* tmp = head_;
Node* tmp2 = head_;
if (/*my_list.*/empty() == true)
{
return *this;
}
while (tmp->next != nullptr)
{
tmp = tmp->next;
if (tmp->next == nullptr) break;
tmp = tmp->next;
tmp2 = tmp2->next;
}
my_list.head_ = tmp2->next;
tmp2->next = nullptr;
my_list.size_ = size_/2;
size_ = size_ - my_list.size_;
return my_list;
}
int main() {
Forward_list<int> fw;
for (int i{}; i < 3; ++i)
fw.push_back(i);
Forward_list<int> fw2 = fw.split();
}

How to do right template outputs in c++

i have this error in MSVS project, in this part of code
ostream& getStream(ostream& out)
{
for (Node* temp = head; temp; temp = temp->next)
out << temp->info << " ";
return out;
}
Error C2679 binary"<<": no operator was found that accepts the right operand of type " T " (or there is no acceptable conversion)
#pragma once
#ifndef _LIST_H_
#define _LIST_H_
#include <iostream>
using namespace std;
template <class T>
class MyList
{
protected :
struct Node
{
T info;
Node* next;
Node(T info, Node* next = 0) :
info(info),
next(next)
{}
};
Node* head;
ostream& getStream(ostream& out)
{
for (Node* temp = head; temp; temp = temp->next)
out << temp->info << " ";
return out;
}
public:
MyList();
~MyList();
template <class T1>
friend ostream& operator<<(ostream& os, MyList<T1>& list);
void Insert(T info, int index);
int Count();
void Remove(int index);
void PopFront();
void PushFront(T Data);
void PopBack();
void PushBack(T Data);
};
template <class T>
MyList<T>::MyList():
head(0)
{}
template <class T>
MyList<T>::~MyList()
{
while (head != NULL)
{
Node* help = head->next;
delete head;
head = help;
}
}
template <class T>
ostream& operator<<(ostream& out, MyList<T>& list)
{
return list.getStream(out);
}
template <class T>
void MyList<T>::Insert(T info, int index)
{
if (Count() < index || index < 0) throw 1;
if (index == 0)
{
head = new Node(info, head);
return;
}
Node* current = head;
for (int i = 1; i < index; current = current->next, i++);
current->next = new Node(info, current->next);
}
template <class T>
void MyList<T>::Remove(int index)
{
if (Count() <= index || index < 0) throw 1;
if (index == 0)
{
Node* help = head->next;
delete head;
head = help;
return;
}
Node* current = head;
for (int i = 1; i < index; current = current->next, i++);
Node* help = current->next;
current->next = help->next;
delete help;
}
template <class T>
void MyList<T>::PopFront()
{
if (head == 0) return;
Node* help = head;
head = head->next;
delete help;
}
template<class T>
void MyList<T>::PushFront(T Data)
{
head = new Node(Data, head);
}
template<class T>
void MyList<T>::PopBack()
{
if (head == 0)return;
if (Count() == 1)
{
delete head;
head = 0;
}
Node* curr;
for (curr = head; curr->next->next != 0; curr = curr->next);
delete curr->next;
curr->next = 0;
}
template<class T>
void MyList<T>::PushBack(T Data)
{
Node* curr;
for (curr = head; curr->next != 0; curr = curr->next);
curr->next = new Node(Data);
}
template <class T>
int MyList<T>::Count()
{
int count = 0;
for (Node* current = head; current != NULL; current = current->next, count++);
return count;
}
#endif // !_LIST_H_
this is declaration of my class
i have no ideas how to fix it,
big thank to you if you will try to help me
sory if have bad description, im only starting
one of descendant of my class have bad implementation of operator<<, and that class jump me to this problem

C++ Creating a Linked List With More Than 2 Fields per Node

So I am attempting to create a Linked List that can store books for a imaginative library. Within the linked list, each node should contain the branch of library, the author's name, the book's title, and the number of copies of said book.
I'm having difficulty creating a linked list with multiple fields per node. How would I go about it so that each node can store 3 separate strings and an integer, and then finally, a pointer to the next node?
Here is my current code.
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <stdexcept>
using namespace std;
template<typename T>
class Node
{
public:
T element;
Node<T>* next;
Node()
{
next = nullptr;
}
Node(T element) // Constructor
{
this->element = element;
next = nullptr;
}
};
template<typename T>
class Iterator : public std::iterator<std::forward_iterator_tag, T>
{
public:
Iterator(Node<T>* p)
{
current = p;
}
Iterator operator++() // Prefix ++
{
current = current->next;
return *this;
}
Iterator operator++(int dummy) // Postfix ++
{
Iterator temp(current);
current = current->next;
return temp;
}
T& operator*()
{
return current->element;
}
bool operator==(const Iterator<T>& iterator)
{
return current == iterator.current;
}
bool operator!=(const Iterator<T>& iterator)
{
return current != iterator.current;
}
private:
Node<T>* current;
};
template<typename T>
class LinkedList
{
public:
LinkedList();
LinkedList(const LinkedList<T>& list);
virtual ~LinkedList();
void addFirst(T element);
void addLast(T element);
T getFirst() const;
T getLast() const;
T removeFirst() throw (runtime_error);
T removeLast();
void add(T element);
void add(int index, T element);
void clear();
bool contains(T element) const;
T get(int index) const;
int indexOf(T element) const;
bool isEmpty() const;
int lastIndexOf(T element) const;
void remove(T element);
int getSize() const;
T removeAt(int index);
T set(int index, T element);
Iterator<T> begin() const
{
return Iterator<T>(head);
}
Iterator<T> end() const
{
return Iterator<T>(tail->next);
}
private:
Node<T>* head;
Node<T>* tail;
int size;
};
template<typename T>
LinkedList<T>::LinkedList()
{
head = tail = nullptr;
size = 0;
}
template<typename T>
LinkedList<T>::LinkedList(const LinkedList<T>& list)
{
head = tail = nullptr;
size = 0;
Node<T>* current = list.head;
while (current != nullptr)
{
this->add(current->element);
current = current->next;
}
}
template<typename T>
LinkedList<T>::~LinkedList()
{
clear();
}
template<typename T>
void LinkedList<T>::addFirst(T element)
{
Node<T>* newNode = new Node<T>(element);
newNode->next = head;
head = newNode;
size++;
if (tail == nullptr)
tail = head;
}
template<typename T>
void LinkedList<T>::addLast(T element)
{
if (tail == nullptr)
{
head = tail = new Node<T>(element);
}
else
{
tail->next = new Node<T>(element);
tail = tail->next;
}
size++;
}
template<typename T>
T LinkedList<T>::getFirst() const
{
if (size == 0)
throw runtime_error("Index out of range");
else
return head->element;
}
template<typename T>
T LinkedList<T>::getLast() const
{
if (size == 0)
throw runtime_error("Index out of range");
else
return tail->element;
}
template<typename T>
T LinkedList<T>::removeFirst() throw (runtime_error)
{
if (size == 0)
throw runtime_error("No elements in the list");
else
{
Node<T>* temp = head;
head = head->next;
if (head == nullptr) tail = nullptr;
size--;
T element = temp->element;
delete temp;
return element;
}
}
template<typename T>
T LinkedList<T>::removeLast()
{
if (size == 0)
throw runtime_error("No elements in the list");
else if (size == 1)
{
Node<T>* temp = head;
head = tail = nullptr;
size = 0;
T element = temp->element;
delete temp;
return element;
}
else
{
Node<T>* current = head;
for (int i = 0; i < size - 2; i++)
current = current->next;
Node<T>* temp = tail;
tail = current;
tail->next = nullptr;
size--;
T element = temp->element;
delete temp;
return element;
}
}
template<typename T>
void LinkedList<T>::add(T element)
{
addLast(element);
}
template<typename T>
void LinkedList<T>::add(int index, T element)
{
if (index == 0)
addFirst(element);
else if (index >= size)
addLast(element);
else
{
Node<T>* current = head;
for (int i = 1; i < index; i++)
current = current->next;
Node<T>* temp = current->next;
current->next = new Node<T>(element);
(current->next)->next = temp;
size++;
}
}
template<typename T>
void LinkedList<T>::clear()
{
while (head != nullptr)
{
Node<T>* temp = head;
head = head->next;
delete temp;
}
tail = nullptr;
size = 0;
}
template<typename T>
T LinkedList<T>::get(int index) const
{
if (index < 0 || index > size - 1)
throw runtime_error("Index out of range");
Node<T>* current = head;
for (int i = 0; i < index; i++)
current = current->next;
return current->element;
}
template<typename T>
int LinkedList<T>::indexOf(T element) const
{
// Implement it in this exercise
Node<T>* current = head;
for (int i = 0; i < size; i++)
{
if (current->element == element)
return i;
current = current->next;
}
return -1;
}
template<typename T>
bool LinkedList<T>::isEmpty() const
{
return head == nullptr;
}
template<typename T>
int LinkedList<T>::getSize() const
{
return size;
}
template<typename T>
T LinkedList<T>::removeAt(int index)
{
if (index < 0 || index >= size)
throw runtime_error("Index out of range");
else if (index == 0)
return removeFirst();
else if (index == size - 1)
return removeLast();
else
{
Node<T>* previous = head;
for (int i = 1; i < index; i++)
{
previous = previous->next;
}
Node<T>* current = previous->next;
previous->next = current->next;
size--;
T element = current->element;
delete current;
return element;
}
}
// The functions remove(T element), lastIndexOf(T element),
// contains(T element), and set(int index, T element) are
// left as an exercise
#endif
Given a struct, such as
struct Book
{
std::string branch;
std::string author;
std::string title;
int copies;
};
A LinkedList<Book> would have all the data elements you want in each Node.

Linked List of linked lists trouble

I am having trouble implementing this with the class I have. So far as a linkedlist of type int or string it works great, but I am not sure how to navigate the list if I initialize it like
linkedlist<linkedlist<int>> nums;
From my program it seems that the head of each secondary list would be an entry in the primary, but my question is how would I navigate it?. For example how would I print all the values of each linkedlist, I am sure I am making this more difficult than it it, but any help would be appreciated.
/* Node Class */
template <typename T>
class Node {
public:
T data;
Node* next;
Node* previous;
Node(T data);
Node();
T getData();
};
template <typename T>
Node<T>::Node() {
this->next = NULL;
this->previous = NULL;
}
template <typename T>
Node<T>::Node(T data) {
this->data = data;
}
template <typename T>
T Node<T>::getData() {
return this->data;
}
/* Linked List: */
template <typename T>
class linkedlist {
private:
Node<T>* head;
Node<T>* tail;
int list_size;
public:
linkedlist();
T getHead();
T getTail();
int size();
void addnodetail(T);
void addnodehead(T);
void push(T);
T pop();
//T* peek();
bool isEmpty() const {
return head == NULL;
}
//T* get(int index);
void printlist();
void printListBackwards();
~linkedlist();
};
template <typename T>
linkedlist<T>::linkedlist() {
this->head = NULL;
this->tail = NULL;
this->list_size = 0;
}
template <typename T>
T linkedlist<T>::getHead() {
return this->head->data;
}
template <typename T>
T linkedlist<T>::getTail() {
return this->tail->data;
}
template <class T>
int linkedlist<T>::size() {
return this->list_size;
}
template <typename T>
void linkedlist<T>::addnodetail(T input) {
Node<T>* newnode = new Node<T>(input);
newnode->next = NULL;
newnode->previous = NULL;
if (this->head == NULL) {
this->head = newnode;
this->tail = this->head;
this->list_size = this->list_size + 1;
} else {
this->tail->next = newnode;
newnode->previous = this->tail;
this->tail = newnode;
this->list_size = this->list_size + 1;
}
}
template <typename T>
void linkedlist<T>::addnodehead(T input) {
Node<T>* newnode = new Node<T>(input);
newnode->next = NULL;
newnode->previous = NULL;
if (this->head == NULL) {
this->head = newnode;
this->tail = this->head;
this->list_size = this->list_size + 1;
} else {
this->head->previous = newnode;
newnode->next = this->head;
this->head = newnode;
this->list_size = this->list_size + 1;
}
}
template <typename T>
void linkedlist<T>::push(T input) {
this->addnodehead(input);
}
template <typename T>
T linkedlist<T>::pop() {
Node<T>* temp = this->head;
// T* temp = this->head;
this->head = this->head->next;
this->head->previous = NULL;
this->list_size = this->list_size - 1;
return temp->data;
}
/*
template <class T>
T* MyList<T>::peek() {
return this->head;
}
template <class T>
T* MyList<T>::get(int index) {
if (index == 0) {
return this->head;
} else if (index == this->list_size - 1) {
return this->tail;
} else if (index < 0 || index >= this->list_size) {
return NULL;
}
if (index < this->list_size / 2) {
T* temp = this->head;
int i = 0;
while (temp) {
if (i == index) { return temp; }
i++;
temp = temp->next;
}
} else {
T* temp = this->tail;
int i = this->list_size - 1;
while (temp) {
if (i == index) { return temp; }
i--;
temp = temp->previous;
}
}
return NULL;
}*/
template <typename T>
void linkedlist<T>::printlist() {
cout << "HEAD: ";
Node<T>* temp = this->head;
while(temp) {
cout << temp->data << " -> ";
temp = temp->next;
}
cout << "\b\b\b\b :TAIL" << endl;
}
template <class T>
void linkedlist<T>::printListBackwards() {
cout << "TAIL: ";
Node<T>* temp = this->tail;
while(temp) {
cout << temp->data << " -> ";
temp = temp->previous;
}
cout << "\b\b\b\b :HEAD" << endl;
}
template <typename T>
linkedlist<T>::~linkedlist() {
for(Node<T>* p;!isEmpty();){
p = head->next;
delete head;
head = p;
}
}
EDIT with copy constructor
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
#include <ctype.h>
using namespace std;
using namespace std;
/*struct AdjListNode
{
int dest;
struct AdjListNode* next;
};
// A structure to represent an adjacency list
struct AdjList
{
struct AdjListNode *head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
};
// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest)
{
struct AdjListNode* newNode =
(struct AdjListNode*) malloc(sizeof(struct AdjListNode));
newNode->dest = dest;
newNode->next = NULL;
return newNode;
}
// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
graph->V = V;
// Create an array of adjacency lists. Size of array will be V
graph->array = (struct AdjList*) malloc(V * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
int i;
for (i = 0; i < V; ++i)
graph->array[i].head = NULL;
return graph;
}
// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest)
{
// Add an edge from src to dest. A new node is added to the adjacency
// list of src. The node is added at the begining
struct AdjListNode* newNode = newAdjListNode(dest);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
// Since graph is undirected, add an edge from dest to src also
newNode = newAdjListNode(src);
newNode->next = graph->array[dest].head;
graph->array[dest].head = newNode;
}
// A utility function to print the adjacenncy list representation of graph
void printGraph(struct Graph* graph)
{
int v;
for (v = 0; v < graph->V; ++v)
{
struct AdjListNode* pCrawl = graph->array[v].head;
printf("\n Adjacency list of vertex %d\n head ", v);
while (pCrawl)
{
printf("-> %d", pCrawl->dest);
pCrawl = pCrawl->next;
}
printf("\n");
}
}
*/
/* Node Class */
template <typename T>
class Node {
public:
T data;
Node* next;
Node* previous;
Node(T data);
Node();
T getData();
};
template <typename T>
Node<T>::Node() {
this->next = NULL;
this->previous = NULL;
}
template <typename T>
Node<T>::Node(T data) {
this->data = data;
this->next = NULL;
}
template <typename T>
T Node<T>::getData() {
return this->data;
}
/* Linked List: */
template <typename T>
class linkedlist {
private:
Node<T>* head;
Node<T>* tail;
int list_size;
public:
linkedlist();
linkedlist(linkedlist& object);
T getHead();
T getTail();
int size();
void addtail(const T& input);
void addhead(const T& input);
void push(T);
T pop();
//T* peek();
bool isEmpty() const {
return head == NULL;
}
//T* get(int index);
void printlist();
void printListBackwards();
~linkedlist();
};
template <typename T>
linkedlist<T>::linkedlist() {
this->head = NULL;
this->tail = NULL;
this->list_size = 0;
}
template <typename T>
linkedlist<T>::linkedlist(linkedlist &object){
if(object.head == NULL){
head == NULL;
}
else {
head = new Node<T>(object.head->data);
Node<T>* temp = head;
Node<T>* objecthead = object.head;
Node<T>* current = objecthead;
while(current->next != NULL){
temp->next = new Node<T>(current->next->data);
current = current->next;
temp = temp->next;
}
}
}
template <typename T>
T linkedlist<T>::getHead() {
return this->head->data;
}
template <typename T>
T linkedlist<T>::getTail() {
return this->tail->data;
}
template <class T>
int linkedlist<T>::size() {
return this->list_size;
}
template <typename T>
void linkedlist<T>::addtail(const T& input) {
Node<T>* newnode = new Node<T>(input);
newnode->next = NULL;
newnode->previous = NULL;
if (this->head == NULL) {
this->head = newnode;
this->tail = this->head;
this->list_size = this->list_size + 1;
} else {
this->tail->next = newnode;
newnode->previous = this->tail;
this->tail = newnode;
this->list_size = this->list_size + 1;
}
}
template <typename T>
void linkedlist<T>::addhead(const T& input) {
Node<T>* newnode = new Node<T>(input);
newnode->next = NULL;
newnode->previous = NULL;
if (this->head == NULL) {
this->head = newnode;
this->tail = this->head;
this->list_size = this->list_size + 1;
} else {
this->head->previous = newnode;
newnode->next = this->head;
this->head = newnode;
this->list_size = this->list_size + 1;
}
}
template <typename T>
void linkedlist<T>::push(T input) {
this->addhead(input);
}
template <typename T>
T linkedlist<T>::pop() {
Node<T>* temp = this->head;
if(temp != NULL){
this->head = this->head->next;
this->head->previous = NULL;
this->list_size = this->list_size - 1;
return temp->data;
}
else{
cout << "Error:Empty List!";
exit (EXIT_FAILURE);
}
}
/*
template <class T>
T* MyList<T>::peek() {
return this->head;
}
template <class T>
T* MyList<T>::get(int index) {
if (index == 0) {
return this->head;
} else if (index == this->list_size - 1) {
return this->tail;
} else if (index < 0 || index >= this->list_size) {
return NULL;
}
if (index < this->list_size / 2) {
T* temp = this->head;
int i = 0;
while (temp) {
if (i == index) { return temp; }
i++;
temp = temp->next;
}
} else {
T* temp = this->tail;
int i = this->list_size - 1;
while (temp) {
if (i == index) { return temp; }
i--;
temp = temp->previous;
}
}
return NULL;
}*/
template <typename T>
void linkedlist<T>::printlist() {
cout << "STACK" << endl;
cout << "-------------------" << endl;
Node<T>* temp = this->head;
while(temp) {
cout << "\t" << temp->data << endl;
temp = temp->next;
}
//cout << "\b\b\b\b :TAIL" << endl;
}
template <class T>
void linkedlist<T>::printListBackwards() {
cout << "TAIL: ";
Node<T>* temp = this->tail;
while(temp) {
cout << temp->data << " -> ";
temp = temp->previous;
}
cout << "\b\b\b\b :HEAD" << endl;
}
template <typename T>
linkedlist<T>::~linkedlist() {
for(Node<T>* p;!isEmpty();){
p = head->next;
delete head;
head = p;
}
}
#endif // LINKEDLIST_H

C++ object get a residual value after a for loop

I created a class for queue an I'm using an object of that class in a loop. After an iteration the value of the first element in queue change to a residual value. Why is that and how can I fix it?
Here's the .h file:
#ifndef QUEUE_H
#define QUEUE_H
#include "headers.h"
template <class T>
class Queue
{
public:
Queue();
~Queue();
void Push(T value); // Insert a new element at the end of the queue.
void Display(); // Display the queue.
T Pop(); // Delete the top of the queue and returns it.
T Peek(); // Returns the top of the queue.
T GetPositionValue(uint pos); // Returns the value found on the specified position.
T GetMin(); // Returns the lowest value in the queue.
T GetMax(); // Returns the highest value in the queue.
uint Distance(T value); // Returns -1 if the value isn't in the queue, else returns the distance from the top.
uint GetSize() const { return size; } // Returns the number of elements found in the stack.
bool IsEmpty() { return (first == nullptr); } // Returns true if the queue is empty.
bool HasValue(T value); // Returns true if the value is in the queue.
bool HasPosition(uint pos); // Returns true if pos is found in queue. Position 0 is top.
private:
struct Node
{
T value;
Node *next;
};
Node *first, *last;
uint size;
Node *GetPositionAddress(uint pos);
Node *GetValueAddress(T value);
};
template <class T>
class Deque
{
public:
Deque();
~Deque();
void PushBack(T value);
void PushFront(T value);
void Display();
T PopFront();
T PeekFront();
T PopEnd();
T PeekEnd();
T GetPositionValue(uint pos);
T GetMin();
T GetMax();
uint Distance(T value);
uint GetSize() const { return size; }
bool IsEmpty() { return (first == nullptr); }
bool HasValue(T value);
bool HasPosition(uint pos);
private:
struct Node
{
T value;
Node *next;
};
Node *first, *last;
uint size;
Node *GetPositionAddress(uint pos);
Node *GetValueAddress(T value);
};
#include "Queue.cpp"
#endif
Here's where the queue is used.
#include "../Headers/queue.h"
// Simple linked list of queues
struct SLLQ
{
Deque<int> deq;
SLLQ *next;
};
void CreateStorage(SLLQ *&head, SLLQ *&tail)
{
SLLQ *elem = new SLLQ;
elem->next = NULL;
if (!head)
{
head = elem;
tail = elem;
}
else
{
tail->next = elem;
tail = elem;
}
}
int main()
{
std::ifstream f("Inputs/hw4p7.in");
int k, k2, n;
Queue<int> laneIN, laneOUT;
SLLQ *sqf = NULL, *sql = NULL;
f >> k;
k2 = k;
f >> n;
for (int i = 0; i < n; i++)
{
int value;
f >> value;
laneIN.Push(value);
}
k--;
CreateStorage(sqf, sql);
sqf->deq.PushBack(laneIN.Pop());
// Inserting the wagons in the storage lines
for (int i = 1; i < n; i++)
{
if (sqf->deq.PeekEnd() < laneIN.Peek())
sqf->deq.PushBack(laneIN.Pop());
else
{
SLLQ *temp = sqf;
bool pushed = false;
while (!pushed)
{
if (!temp->next)
{
// End the program if he use to much storage lanes
if (!k)
{
std::cout << "There's no strategy with " << k2 << " storage lanes.";
_getch();
return;
}
k--;
CreateStorage(sqf, sql);
temp = temp->next;
temp->deq.PushBack(laneIN.Pop());
pushed = true;
}
else
{
temp = temp->next;
if (temp->deq.PeekEnd() < laneIN.Peek())
{
temp->deq.PushBack(laneIN.Pop());
pushed = true;
}
}
}
}
}
// Inserting the wagons in the out lane
for (int i = 0; i < n; i++)
{
SLLQ *temp = sqf;
Deque<int> mina = temp->deq;
temp = temp->next;
while (temp)
{
if (temp->deq.PeekFront() < mina.PeekFront())
mina = temp->deq;
temp = temp->next;
}
SLLQ *minadd = sqf;
SLLQ *predminadd = sqf;
while (minadd && (minadd->deq.PeekFront() != mina.PeekFront()))
{
minadd = minadd->next;
if (predminadd->next != minadd)
predminadd = predminadd->next;
}
laneOUT.Push(minadd->deq.PopFront());
if (minadd->deq.IsEmpty())
{
delete minadd;
predminadd->next = nullptr;
}
}
laneOUT.Display();
_getch();
return 0;
}
Here's the .cpp file with queue members definitions:
#include "queue.h"
template<class T>
Queue<T>::Queue()
{
first = last = nullptr;
size = 0;
}
template<class T>
Queue<T>::~Queue()
{
while (first)
{
typename Queue<T>::Node *del = first;
first = first->next;
delete del;
}
first = last = nullptr;
size = 0;
}
template <class T>
void Queue<T>::Push(T value)
{
typename Queue<T>::Node *elem = new Node;
elem->value = value;
elem->next = nullptr;
if (first)
last->next = elem;
else
first = elem;
last = elem;
size++;
}
template <class T>
void Queue<T>::Display()
{
typename Queue<T>::Node *temp = first;
while (temp)
{
std::cout << temp->value << "\n";
temp = temp->next;
}
}
template <class T>
T Queue<T>::Pop()
{
if (IsEmpty())
return T(-1);
T value = first->value;
typename Queue<T>::Node *temp = first;
first = first->next;
delete temp;
if (first == nullptr)
last = nullptr;
size--;
return value;
}
template <class T>
T Queue<T>::Peek()
{
if (IsEmpty())
return T(-1);
return first->value;
}
template <class T>
T Queue<T>::GetPositionValue(uint pos)
{
if (IsEmpty() || !HasPosition(pos))
return T(-1);
typename Queue<T>::Node *temp = first;
for (uint i = 1; i < pos; i++)
temp = temp->next;
return temp->value;
}
template <class T>
uint Queue<T>::Distance(T value)
{
uint distance = 0;
if (!HasValue(value))
return -1;
typename Queue<T>::Node *temp = first;
while (temp && temp->value != value)
{
temp = temp->next;
distance++;
}
return distance;
}
template <class T>
T Queue<T>::GetMin()
{
if (IsEmpty())
return T();
T min = first->value;
typename Queue<T>::Node *temp = first;
while (temp->next)
{
temp = temp->next;
if (temp->value < min)
min = temp->value;
}
return min;
}
template <class T>
T Queue<T>::GetMax()
{
if (IsEmpty())
return T();
T max = first->value;
typename Queue<T>::Node *temp = first;
while (temp->next)
{
temp = temp->next;
if (temp->value > max)
max = temp->value;
}
return max;
}
template <class T>
bool Queue<T>::HasValue(T value)
{
typename Queue<T>::Node *temp = first;
while (temp && temp->value != value)
temp = temp->next;
if (!temp)
return false;
else
return true;
}
template <class T>
bool Queue<T>::HasPosition(uint pos)
{
if (IsEmpty())
return false;
uint i = 1;
typename Queue<T>::Node *temp = first;
while (temp && i < pos)
{
temp = temp->next;
i++;
}
if (i == pos)
return true;
else
return false;
}
// Private members
template <class T>
typename Queue<T>::Node *Queue<T>::GetPositionAddress(uint pos)
{
if (IsEmpty() || !HasPosition(pos))
return nullptr;
Node *temp = first;
for (uint i = 1; i < pos; i++)
temp = temp->next;
return temp;
}
template <class T>
typename Queue<T>::Node *Queue<T>::GetValueAddress(T value)
{
if (IsEmpty() || !HasValue(value))
return nullptr;
Node *temp = first;
while (temp->value != value)
temp = temp->next;
return temp;
}
// Deque
template <class T>
Deque<T>::Deque()
{
first = last = nullptr;
size = 0;
}
template <class T>
Deque<T>::~Deque()
{
while (first)
{
typename Deque<T>::Node *del = first;
first = first->next;
delete del;
}
first = last = nullptr;
size = 0;
}
template <class T>
void Deque<T>::PushBack(T value)
{
typename Deque<T>::Node *elem = new Node;
elem->value = value;
elem->next = nullptr;
if (first)
last->next = elem;
else
first = elem;
last = elem;
size++;
}
template <class T>
void Deque<T>::PushFront(T value)
{
typename Deque<T>::Node *elem = new Node;
elem->value = value;
elem->next = nullptr;
if (first)
elem->next = first;
else
last = elem;
first = elem;
size++;
}
template <class T>
void Deque<T>::Display()
{
typename Deque<T>::Node *temp = first;
while (temp)
{
std::cout << temp->value << "\n";
temp = temp->next;
}
}
template <class T>
T Deque<T>::PopFront()
{
if (IsEmpty())
return T(-1);
T value = first->value;
typename Deque<T>::Node *temp = first;
first = first->next;
delete temp;
if (first == nullptr)
last = nullptr;
size--;
return value;
}
template <class T>
T Deque<T>::PeekFront()
{
if (IsEmpty())
return T(-1);
return first->value;
}
template <class T>
T Deque<T>::PopEnd()
{
if (IsEmpty())
return T(-1);
if (first == last)
return PopFront();
T value = last->value;
typename Deque<T>::Node *temp = first;
while (temp && temp->next != last)
temp = temp->next;
delete last;
last = temp;
size--;
return value;
}
template <class T>
T Deque<T>::PeekEnd()
{
if (IsEmpty())
return T(-1);
return last->value;
}
template <class T>
T Deque<T>::GetPositionValue(uint pos)
{
if (IsEmpty() || !HasPosition(pos))
return T(-1);
typename Deque<T>::Node *temp = first;
for (uint i = 1; i < pos; i++)
temp = temp->next;
return temp->value;
}
template <class T>
uint Deque<T>::Distance(T value)
{
uint distance = 0;
if (!HasValue(value))
return -1;
typename Deque<T>::Node *temp = first;
while (temp && temp->value != value)
{
temp = temp->next;
distance++;
}
return distance;
}
template <class T>
T Deque<T>::GetMin()
{
if (IsEmpty())
return T();
T min = first->value;
typename Deque<T>::Node *temp = first;
while (temp->next)
{
temp = temp->next;
if (temp->value < min)
min = temp->value;
}
return min;
}
template <class T>
T Deque<T>::GetMax()
{
if (IsEmpty())
return T();
T max = first->value;
typename Deque<T>::Node *temp = first;
while (temp->next)
{
temp = temp->next;
if (temp->value > max)
max = temp->value;
}
return max;
}
template <class T>
bool Deque<T>::HasValue(T value)
{
typename Deque<T>::Node *temp = first;
while (temp && temp->value != value)
temp = temp->next;
if (!temp)
return false;
else
return true;
}
template <class T>
bool Deque<T>::HasPosition(uint pos)
{
if (IsEmpty())
return false;
uint i = 1;
typename Deque<T>::Node *temp = first;
while (temp && i < pos)
{
temp = temp->next;
i++;
}
if (i == pos)
return true;
else
return false;
}
// Private members
template <class T>
typename Deque<T>::Node *Deque<T>::GetPositionAddress(uint pos)
{
if (IsEmpty() || !HasPosition(pos))
return nullptr;
Node *temp = first;
for (uint i = 1; i < pos; i++)
temp = temp->next;
return temp;
}
template <class T>
typename Deque<T>::Node *Deque<T>::GetValueAddress(T value)
{
if (IsEmpty() || !HasValue(value))
return nullptr;
Node *temp = first;
while (temp->value != value)
temp = temp->next;
return temp;
}
The problem is at line 114(third for) where the queue is used, precisely: "laneOUT.Push(minadd->deq.PopFront());"
It puts the value in laneOUT but at next iteration it changes to a residual value.
After almost three years I came across this old question of mine and remembered I wasn't able to fix this code back then, so I thought I would give it a try now that I know so much more.
A big no no can be spotted right away in the second statement of the third for-loop from the main function:
Deque<int> mina = temp->deq;
This code performs a copy, but the Deque class has no copy-constructor implemented explicitly although it manage resources.
The implicit copy-constructor will perform a shallow copy and after the first iteration of the for-loop, the mina object will be destroyed but the memory deallocated is still pointed to by temp->deq used to initialize mina, in the first iteration, without any knowledge that the memory it points to is deallocated.
The Rule of Three (Five in C++11) must be respected when a class manages resources.