I'm trying to implement a Queue using a linked list, but I get this error when I pass an integer to the enqueue function in main
Exception thrown: write access violation.
this->tail was nullptr.
here is my Queue.h
#include <iostream>
using namespace std;
template <class T >
class Node
{
public:
T data;
Node* next;
Node();
Node(T _data);
};
template <class T>
class Queue
{
public:
Node<T> *head, *tail;
int elemsCnt;
Queue();
~Queue();
int count();
void clear();
void enqueue(T);
T dequeue();
T front();
T back();
bool empty();
};
and this is my Queue.cpp which i wrote the functions ..
#include "Queue.h"
template <class T>
Node<T>::Node()
{
next = NULL;
}
template <class T>
Node<T>::Node(T _data)
{
data = _data;
next = NULL;
}
template <class T>
Queue<T>::Queue()
{
head = tail = NULL;
elemsCnt = 0;
}
template <class T>
Queue<T>::~Queue()
{
clear();
}
template <class T>
int Queue<T>::count()
{
return elemsCnt;
}
template <class T>
bool Queue<T>::empty()
{
return(elemsCnt == 0);
}
template <class T>
void Queue<T>::enqueue(T val)
{
Node<T>* inserted = new Node<T>(val);
tail->next = inserted;
tail = inserted;
++elemsCnt;
}
template <class T>
T Queue<T>::dequeue()
{
Node<T>* deleted = head;
T val = head->data;
head = head->next;
delete deleted;
--elemsCnt;
if (empty())
tail = NULL;
return val;
}
template <class T>
T Queue<T>::front()
{
return head->data;
}
template <class T>
T Queue<T>::back()
{
return tail->data;
}
template <class T>
void Queue<T>::clear()
{
while (!empty())
{
Node<T>* deleted = head;
head = head->next;
delete deleted;
--elemsCnt;
}
tail = NULL;
}
because initially your Queue is empty. when you have:
void Queue<T>::enqueue(T val)
{
Node<T>* inserted = new Node<T>(val);
tail->next = inserted; //at this point tail is still NULL
//it is illegal to try to access * and . on NULL
tail = inserted;
++elemsCnt;
}
if you want to fix it try this:
void Queue<T>::enqueue(T val)
{
Node<T>* inserted = new Node<T>(val);
if(this->elemsCnt==0)
{
//empty Queue
this->head=inserted;
this->tail=inserted;
}
else
{
//non empty
inserted->next=this->head; //make sure the new head can point to older head
this->head=inserted; update the pointer for head.
}
++elemsCnt;
}
just like the exception says, tail is NULL. Your enqueue method is not handling the case when the list is empty (head == tail == null).
template <class T>
void Queue<T>::enqueue(T val)
{
Node<T>* inserted = new Node<T>(val);
if (head == NULL)
{
head = tail = inserted;
}
else
{
tail->next = inserted;
tail = inserted;
}
++elemsCnt;
}
Related
Where is the problem in my customLinkedList???
I have create that customLinkedList, that can contain all type of values.
I don't know where is the problem...
on the last line of the main appear the error "expression must have class type".
Someone can help me?
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
/*
struct ha tutte le variabili pubbliche
*/
//CLASS NODE
template <class T>
class Node {
public:
T data;
Node<T>*next;
Node();
Node(T v);
Node<T>(T v, Node *nextNode);
T getValue();
};
template <class T>
Node<T>::Node() {
data = null;
next = nullptr;
}
template <class T>
Node<T>::Node(T v) {
data = v;
next = NULL;
}
template <class T>
Node<T>::Node(T v, Node *nextNode) {
data = v;
next = nextNode;
}
template <class T>
T Node<T>::getValue() {
return data;
}
/*-------------------------------------------------------------------------------------------------*/
/*
class tutte le variabili private.
uso etichetta public: per avere variabili e funzioni pubbliche
*/
//CLASS LIST
template <class T>
class List {
Node<T> *head;
public:
List();
~List();
void addFirst(T v);
void deleteN(T v);
Node<T> *find(T v);
};
template <class T>
List<T>::List() {
head = NULL;
}
template <class T>
List<T>::~List() {
Node<T> *tmp = head;
while (tmp != NULL) {
tmp = head->next;
delete head;
head = tmp;
}
}
template <class T>
void List<T>::addFirst(T v) {
Node<T> *n = new Node<T>();
n->data = v;
n->next = head;
head = n;
}
template <class T>
Node<T>* List<T>::find(T v) {
Node<T> * tmp = head;
while (tmp->data != v && tmp != NULL) {
tmp = tmp->next;
}
return tmp;
}
template <class T>
void List<T>::deleteN(T v) {
Node<T> *iter = this->head;
Node<T> *temp = iter;
while (iter != NULL) {
if (iter->data == data) {
temp->next = iter->next;
delete iter;
break;
}
else {
temp = iter;
iter = iter->next;
}
}
return;
}
int main() {
Node<int> n1();
Node<int> n2(5);
Node<char> n3('z');
char c = n3.getValue();
printf("%c" , c);
// with Node all work well...
List<string> l1();
l1.addFirst("Hello");
}
I suspect that
List<string> l1();
should be
List<std::string> l1;
string may be defined somewhere and hence cause the error.
I get this error when I try to compile either popRight or popLeft. Why? Here are the codes.
Dequeue class
#include "node.h"
template <class T>
class Dequeue
{
public:
void pushLeft(T data);
void popLeft();
T left();
void pushRight(T data);
void popRight();
T right();
bool empty();
private:
int length;
};
template<typename T>
bool Dequeue<T>::empty()
{
if (length == 0)
{
return true;
}
else
return false;
}
template<typename T>
void Dequeue<T>::pushLeft(T data)
{
if (empty() == true)
{
left->setData(data);
right->setData(data);
}
else if (left->getData() == right->getData())
{
left->setData(data);
}
else
{
node<T> *aux = new node<T>;
aux->setData(data);
left->setPrevious(aux);
aux->setNext(left);
left = aux;
}
length++;
}
template<typename T>
void Dequeue<T>::pushRight(T data)
{
if (empty() == true)
{
right->setData(data);
left->setData(data);
}
else if (right->getData() == left->getData())
{
right->setData(data);
}
else
{
node<T> *aux = new node<T>;
aux->setData(data);
right->setPrevious(aux);
aux->setNext(right);
right = aux;
}
length++;
}
template<typename T>
void Dequeue<T>::popLeft()
{
node<T> *node = left->getNext();
node->setPrevious(NULL);
left = node;
}
template<typename T>
void Dequeue<T>::popRight()
{
node<T> *node = right->getPrevious();
node->setNext(NULL);
right = node;
}
Node Class
template <class T>
class node
{
public:
node(T data);
node(T data, node<T>* next);
T getData();
node<T>* getNext();
void setData(T data);
void setNext(node<T>* next);
void setPrevious(node<T>* previous);
private:
T data;
node<T> *next;
node<T> *previous;
node<T> *left;
node<T> *right;
};
template <typename T>
node<T>::node(T data)
{
this->data = data;
this->next = NULL;
this->previous = NULL;
}
template <typename T>
node<T>::node(T data, node<T>* next)
{
this->data = data;
this->next = next;
this->previous = previous;
}
template <typename T>
T node<T>::getData()
{
return this->data;
}
template <typename T>
node<T>* node<T>::getNext()
{
return this->next;
}
template <typename T>
void node<T>::setData(T data)
{
this->data=data;
}
template <typename T>
void node<T>::setNext(node<T>* next)
{
this->next = next;
}
template <typename T>
void node<T>::setPrevious(node<T>* previous)
{
this->previous = previous;
}
Ive been trying to solve this problem for like an hour but I just can't, can anyone help?
You declared left and right as functions. But it's clear from the way you use them in the rest of the code that they should be variables.
class Dequeue
{
public:
void pushLeft(T data);
void popLeft();
T left;
void pushRight(T data);
void popRight();
T right;
bool empty();
private:
int length;
};
I've implemented a simple STL like Queue for practice purpose.
#ifndef QUEUE_H
#define QUEUE_H
#include <iostream>
#include <stdexcept>
template <typename T>
class queue {
public:
~queue();
bool empty() const;
size_t size() const;
T const& front() const;
T& front();
void push(T const& data);
void push(T&& data);
//void emplace (T&&... args);
// void swap (queue& x);
void pop();
private:
size_t elements = 0;
struct node {
T data;
node *next;
node(T const& data, node* next)
: data(data)
, next(next) {
}
node(T&& data, node* next)
: data(std::move(data))
, next(next) {
}
};
node *head = nullptr;
node *tail = nullptr;
};
template <typename T>
queue<T>::~queue() {
node *curr;
while(head) {
curr = head;
head = head->next;
delete curr;
}
}
template <typename T>
bool queue<T>::empty() const {
return elements == 0;
// return head == nullptr;
}
template <typename T>
size_t queue<T>::size() const {
return elements;
}
template <typename T>
T const& queue<T>::front() const {
if(head == nullptr)
throw std::runtime_error("Invalid Action");
return head->data;
}
template <typename T>
T& queue<T>::front() {
if(head == nullptr)
throw std::runtime_error("Invalid Action");
return head->data;
}
template <typename T>
void queue<T>::push(T const& data) {
node *newNode = new node(data, nullptr);
if(head == nullptr) head = newNode;
else tail->next = newNode;
tail = newNode;
++elements;
}
template <typename T>
void queue<T>::push(T&& data) {
node *newNode = new node(std::move(data), nullptr);
if(head == nullptr) head = newNode;
else tail->next = newNode;
tail = newNode;
++elements;
}
template <typename T>
void queue<T>::pop() {
if(head == nullptr)
throw std::runtime_error("Invalid Action");
node* remove = head;
head = head->next;
delete remove;
--elements;
}
#endif // QUEUE_H
Everything is okay. Can you give me some insights how I can implement C++11 emplace(Args&&... args) and swap(queue& x) efficiently? Complete Code will be appreciated but some idea will suffice.
Thanks in advance!
swap(queue&) just has to swap each member of queue :
template <typename T>
void queue<T>::swap (queue<T>& rhs)
{
std::swap(elements, rhs.elements);
std::swap(head, rhs.head);
std::swap(tail, rhs.tail);
}
For emplace(Args&&... args) you have to add a node constructor to construct T from Args
something like:
struct node {
T data;
node *next;
template <typename ... Ts>
node(node* next, Ts&&...args) :
data(std::forward<Ts>(args)...),
next(next)
{}
};
template <typename T>
template <typename... Ts>
void queue<T>::emplace(Ts&&... args)
{
node *newNode = new node(nullptr, std::forward<Ts>(args)...);
if (head == nullptr) head = newNode;
else tail->next = newNode;
tail = newNode;
++elements;
}
I've created a simple dynamic template list and i'm having some issue clearing the entire list.
List.h
#ifndef LIST_H
#define LIST_H
#include <Node.h>
template <class T> class List
{
public:
typedef Node<T> node_type;
typedef node_type* node_pointer;
typedef T data_type;
typedef T& reference_type;
List();
void push_back(data_type);
reference_type at(int);
void clear();
void swap(int,int);
int size();
private:
int list_size = 0;
node_pointer head, tail;
};
template <class T> List<T>::List()
{
head=NULL;
tail=NULL;
}
template <class T> void List<T>::push_back(data_type data)
{
if(head == NULL) {
head = new node_type(data);
tail = head;
} else {
node_pointer temp = new node_type(data);
temp->setNextNull();
tail->setNext(temp);
tail = tail->getNext();
}
list_size++;
}
template <class T> typename List<T>::reference_type List<T>::at(int x)
{
node_pointer pointer=head;
for(int i=0; i<x; i++)
pointer=pointer->getNext();
return pointer->getData();
}
template <class T> void List<T>::clear()
{
node_pointer pointer = head;
for(int i=0; i<list_size; i++) {
node_pointer temp = pointer;
pointer=pointer->getNext();
delete(temp);
}
head=NULL;
list_size=0;
}
template <class T> void List<T>::swap(int x, int y)
{
data_type buffer=at(x);
at(x)=at(y);
at(y)=buffer;
}
template <class T> int List<T>::size()
{
return list_size;
}
#endif // LIST_H
Node.h
template <class T> class Node
{
public:
typedef T data_type;
typedef T& reference_type;
Node(data_type _data);
void setData(data_type);
void setNextNull();
void setNext(Node*);
reference_type getData();
Node* getNext();
private:
data_type data;
Node* next;
};
template <class T> Node<T>::Node(data_type _data) : data(_data)
{
setNextNull();
}
template <class T> void Node<T>::setData(data_type _data)
{
data=_data;
}
template <class T> void Node<T>::setNextNull()
{
next=NULL;
}
template <class T> void Node<T>::setNext(Node* _next)
{
next=_next;
}
template <class T> typename Node<T>::reference_type Node<T>::getData()
{
return data;
}
template <class T> typename Node<T>::Node* Node<T>::getNext()
{
return next;
}
If I clear the list calling the "clear" method I get all sorts of errors in almost every other method, but if I use the version below the list works perfectly.
template <class T> void List<T>::clear()
{
head=NULL;
tail=NULL;
list_size=0;
}
The problem only appears if I use the delete function to clear memory. How can I solve this issue?
Your code is very dangerious, because you skipped important checks. Try to use following implementation of at():
template <class T> typename List<T>::reference_type List<T>::at(int x)
{
if (x < 0 || x >= list_size || list_size <= 0)
return DATA_WITH_ERROR_FLAG; // since you return data instead of pointer,
// you can't return NULL here
// (you need special constant for error status
// or support it another way)
node_pointer pointer=head;
for(int i=0; i<x; i++)
{
if (!pointer)
return DATA_WITH_ERROR_FLAG;
pointer=pointer->getNext();
}
if (!pointer)
return DATA_WITH_ERROR_FLAG;
return pointer->getData();
}
After it you have to add checks after each at() call. For example, you have to modify swap() to make it safe too:
template <class T> void List<T>::swap(int x, int y)
{
data_type v1=at(x);
data_type v2=at(y);
if (v1 == DATA_WITH_ERROR_FLAG || v2 == DATA_WITH_ERROR_FLAG)
return; // and somehow set error flag!
data_type t=v1;
v1 = v2;
v2 = t;
}
I.e. you need to check correctness everywhere if you don't like such problems. And it is necessary to support returninig of error status to simplify analysis of errors.
Change your clear() method to this:
template <class T> void List<T>::clear()
{
node_pointer pointer = head;
while (pointer != NULL) {
node_pointer temp = pointer-getNext();
delete pointer;
pointer = temp;
}
head=NULL;
tail=NULL;
list_size=0;
}
You have a memory leak in your code. You don't delete all the list by simply pointing head and tail to NULL.
The best way to do this is to create a delete() function then loop through the whole list while it is not empty and delete node by node.
void deleteHead()
{
if(head != NULL)
{
node *temp = head;
head = head->next;
delete temp;
size--;
}
}
bool isEmpty()
{
return head==NULL;
//return size == 0; <-- this is ok as well.
}
void clear()
{
while(! isEmpty())
{
deleteHead();
}
tail = head; //head = NULL
}
I want to create a factory, that returns AVLNode, if BinaryTree is AVLTree, and Node if the tree is not AVL. I have following code:
#include "BinaryTree.h"
#include "AVLTree.h"
class NodeFactory {
public :
template <class T>
static Node<T>* getNode(BinaryTree<T>* tree);
};
template <class T>
Node<T>* NodeFactory::getNode(BinaryTree<T>* tree) {
if (tree->isAVL()) {
return new AVLNode<T>();
} else {
return new Node<T>();
}
}
UPD: (this is BinaryTree.h)
template <class T> class Node;
template <class T> class BinaryTree {
public:
BinaryTree() {
_isAVL = false;
root = new Node<T>();
}
bool isAVL() {
return _isAVL;
}
private:
T elem;
Node<T>* root;
bool _isAVL;
};
template <class T> class Node {
public:
Node() {
left = NULL;
right = NULL;
}
T get() {
return elem;
}
void setRight(const T elem) {
right = new Node<T>();
right->set(elem);
}
void setLeft(const T elem) {
left = new Node<T>();
left->set(elem);
}
private:
T elem;
Node* left;
Node* right;
};
I removed almost all methods to make code more readable.
Now i have this error during compilation: "expected initializer before '<' token". Also Qt do not highlights in Node, but highlights in BinaryTree
It's a syntax error. You need
template <class T> // or <typename T>
Node<T>* NodeFactory::getNode(BinaryTree<T>* tree) {