So i am coding a browser tab structure, and i have 5 custom class, Stack, LinkedList, Node(for linked list), Tab and Browser.
LinkedList and Stack works fine on their own, but when i construct a LinkedList in Browser's constructer i get error. So in my main i only call Browser().Here are the codes:
LinkedList<T>::LinkedList(){
front=NULL;
back=NULL;
}`
Node<T>::Node(){
prev=NULL;
next=NULL;
data=T();
}
Stack<T>::Stack(int capacity){ //capacity is optional, this is the default constructor.
this->capacity=capacity;
this->size=0;
this->items=new T[capacity];
}
`
Browser(){
selected = NULL;
//print browser link construction starts
pages= LinkedList<Tab>(); //This line gives the error.
closedPages= Stack<Tab>();
curr_index=-1;
tab_count=0;
}
Tab(){
current_page="";
prevPages=Stack<string>();
nextPages=Stack<string>();
closed_index=-1;
}
What is even funnier is that when i do print insertion, what i see is it first starts and finishes a link construction(without doing any tab construction in between), then does bunch of stack and tab construction, THEN prints the "browser link construction starts" and then goes in to and finishes another link construction and then gives seg fault. So it goes in to link construction twice even tough i hoped it would do only once?
Thanks, and sorry in advance if it is something extremly easy/stupid.
EDIT1: Full LinkedList Code
#ifndef _LINKEDLIST_H_
#define _LINKEDLIST_H_
#include <iostream>
#include <cstddef>
#include <stdexcept>
#include "Node.hpp"
using namespace std;
template <class T>
class LinkedList {
private:
/* pointer to the first node */
Node<T>* front;
/* pointer to the last node */
Node<T>* back;
public:
LinkedList();
LinkedList(const LinkedList<T>& ll);
LinkedList<T>& operator=(const LinkedList<T>& ll);
~LinkedList();
/* returns the first node of the linked list */
Node<T>& getFront() const;
/* returns the last node of the linked list */
Node<T>& getBack() const;
/* returns the node in given "pos"ition of the linked list */
Node<T>& getNodeAt(int pos) const;
/* returns the pointer of the node in given
"pos"ition of the linked list */
Node<T>* getNodePtrAt(int pos) const;
/* inserts a new node containing "data"
after the node "prev"
*/
void insert(Node<T>* prev, const T& data);
/* inserts a new node containing "data"
at "pos"ition in the linked list
*/
void insertAt(int pos, const T& data);
/* erases the given "node" from the linked list */
void erase(Node<T>* node);
/* erases the node in given "pos"ition from the linked list */
void eraseFrom(int pos);
/* clears the contents of the linked list */
void clear();
/* inserts a new node containing "data"
to the front of the linked list
*/
void pushFront(const T& data);
/* inserts a new node containing "data"
to the back of the linked list
*/
void pushBack(const T& data);
/* removes the first node */
void popFront();
/* removes the last node */
void popBack();
/* returns true if the list is empty, false otherwise */
bool isEmpty() const;
/* returns the number of items in the list */
size_t getSize() const;
/* prints the contents of the linked list
one node data per line
assumes the objects in the node have operator<< overloaded
*/
void print() const;
};
template <class T>
LinkedList<T>::LinkedList(){
cout << "list construction starts" << endl;
front=NULL;
back=NULL;
cout << "list construction ends" << endl;
}
//COPY AND ASSIGMENT
template<class T>
LinkedList<T>::LinkedList(const LinkedList<T>& ll){
*this=ll;
}
template<class T>
LinkedList<T>& LinkedList<T>::operator=(const LinkedList<T>& ll){
clear();
Node<T>* temp=&(ll.getFront());
while(temp->getNext()!=NULL){
pushBack(temp->getData());
temp->setNext(temp->getNext());
}
pushBack(temp->getData());
return *this;
}
template<class T>
LinkedList<T>::~LinkedList(){
clear();
}
template <class T>
Node<T>& LinkedList<T>::getFront() const{
return *front;
}
template <class T>
Node<T>& LinkedList<T>::getBack() const{
return *back;
}
template <class T>
Node<T>& LinkedList<T>::getNodeAt(int pos) const{
if(pos<0 or pos>=getSize()){
throw out_of_range("Bad Input");
}
Node<T>* retval=front;
for(int i=0;i<pos;i++){
retval=retval->getNext();
}
return *retval;
}
template <class T>
Node<T>* LinkedList<T>::getNodePtrAt(int pos) const{
if(pos<0 or pos>getSize()){
throw out_of_range("Bad Input");
}
Node<T>* retval=front;
for(int i=0;i<pos;i++){
retval=retval->getNext();
}
return retval;
}
template <class T>
void LinkedList<T>::insert(Node<T>* prev,const T& data){
if(prev==NULL){
pushFront(data);
}
else if(prev==back){
pushBack(data);
}
else{
Node<T>* newNode=new Node<T>();
newNode->setData(data);
prev->getNext()->setPrev(newNode);
newNode->setNext(prev->getNext());
newNode->setPrev(prev);
prev->setNext(newNode);
}
}
template <class T>
void LinkedList<T>::insertAt(int pos,const T& data){
if(pos==0){
pushFront(data);
}
else if(pos==getSize()){
pushBack(data);
}
else{
Node<T>* tmp=getNodePtrAt(pos);
Node<T> newNode;
newNode.setData(data);
tmp->getPrev()->setNext(&newNode);
newNode.setNext(tmp);
newNode.setPrev(tmp->getPrev());
tmp->setPrev(&newNode);
}
}
template <class T>
void LinkedList<T>::pushFront(const T& data){
Node<T>* newNode=new Node<T>();
newNode->setData(data);
if(front==NULL){
front=newNode;
back=newNode;
}
else {
newNode->setNext(front);
front->setPrev(newNode);
front=newNode;
newNode->setPrev(NULL);
}
}
template <class T>
void LinkedList<T>::pushBack(const T& data){
Node<T>* newNode=new Node<T>();
newNode->setData(data);
if(front==NULL){
front=newNode;
back=newNode;
}
else {
newNode->setPrev(back);
back->setNext(newNode);
back=newNode;
newNode->setNext(NULL);
}
}
template <class T>
void LinkedList<T>::erase(Node<T>* node){
if(node==front){
popFront();
}
if(node==back){
popBack();
}
else {
node->getNext()->setPrev(node->getPrev());
node->getPrev()->setNext(node->getNext());
node->setNext(NULL); node->setPrev(NULL);
}
delete node;
}
template <class T>
void LinkedList<T>::eraseFrom(int pos){
Node<T>* tmp=getNodePtrAt(pos);
erase(tmp);
}
template <class T>
void LinkedList<T>::clear(){
while(!isEmpty()){
popFront();
}
}
template <class T>
void LinkedList<T>::popFront(){
Node<T>* tmp;
tmp=front;
if(front==back){
front=NULL;
back=NULL;
}
else{
front=front->getNext();
front->setPrev(NULL);
}
delete tmp;
}
template <class T>
void LinkedList<T>::popBack(){
Node<T>* tmp;
tmp=back;
if(front==back){
front=NULL;
back=NULL;
}
else {
back=back->getPrev();
back->setNext(NULL);
}
delete tmp;
}
template <class T>
bool LinkedList<T>::isEmpty() const{
return front==NULL;
}
template <class T>
size_t LinkedList<T>::getSize() const{
if(front==NULL){
return 0;
}
size_t size=1;
Node<T>* current=front;
while(current->getNext()!=NULL){
size++;
current=current->getNext();
}
return size;
}
template <class T>
void LinkedList<T>::print() const{
Node<T>* current=front;
if(front!=NULL){
while(current->getNext()!=NULL){
cout << current->getData() << endl;
current=current->getNext();
}
cout << current->getData() << endl;
}
}
#endif
Your assignment operator appears to be problematic. In your Browser constructor I see this:
pages = LinkedList<Tab>();
This is actually unnecessary but is triggering your problem. Your 'pages' variable is already default constructed (which is why you see all that activity before the print statement) by the time your Browser constructor code begins. Then you perform the assignment which utilizes your assignment operator.
Your assignment operator is assuming that the source LinkedList object has data, but it does not. It is calling getFront() which dereferences 'front', which is NULL. You should check if it is empty first, which I see you have a method for already (isEmpty()).
Related
I've been given a Node and Stack class in my .h file. I have to implement the copy constructor, assignment operator and destructor and test them in a different test file. While testing the copy constructor after inserting 3 elements its displaying only one element. I don't know what's wrong; here's my .h file for your reference:
#ifndef _STACK_H
#define _STACK_H
#include <iostream>
#include <exception>
using std::ostream;
using std::cout;
using std::endl;
using std::range_error;
// Forward declarations
template <class T> class Stack;
template <class T> class Node;
template <class T> ostream& operator<<(ostream&, const Node<T>&);
// Node class for linked list
template <class T>
class Node {
friend Stack<T>;
public:
Node(T data = T(), Node<T>* next = nullptr) {
_data = data;
_next = next;
}
friend ostream& operator<< <T>(ostream& sout, const Node<T>& x);
private:
T _data;
Node* _next;
};
// Overloaded insertion operator. Must be overloaded for the template
// class T, or this won't work!
template <class T>
ostream& operator<<(ostream& sout, const Node<T>& x) {
sout << "Data: " << x._data;
return sout;
}
// Stack class. Linked-list implementation of a stack. Uses the Node
// class.
template <class T>
class Stack {
public:
// Constructor
Stack();
// Copy constructor, assignment operator, and destructor
// DO NOT IMPLEMENT HERE. SEE BELOW.
Stack(const Stack& rhs);
const Stack& operator=(const Stack& rhs);
~Stack();
void push(const T& data);
const T& top() const;
void pop();
bool empty() const; // Returns 'true' if stack is empty
void dump() const;
//Delete method used for destructor
void nullify();
private:
Node<T>* _head;
Node<T>* _temp1;
Node<T>* _temp2; //pointers
};
template <class T>
Stack<T>::Stack() {
_head = nullptr;
}
template <class T>
Stack<T>::Stack(const Stack<T>& rhs) {
if (rhs._head != nullptr) {
_head = new Node<T>(rhs._head->_data);
_temp1 = _head->_next; //temp1 would be the next one after head
//_temp2 = _temp2->_next;
while (_temp2 != nullptr) {
_temp1 = new Node<T>(_temp2->_data);
_temp1 = _temp1->_next;
_temp2 = _temp2->_next; //temp2 should be the next node after temp1
}
}
else
_head = nullptr;
}
template <class T>
const Stack<T>& Stack<T>::operator=(const Stack<T>& rhs) {
if (this != &rhs) {
nullify();
if (rhs._head != nullptr) {
_head = new Node<T>(rhs._head->_data);
_temp1 = _head->_next; //temp1 would be the next one after head
//_temp2 = _temp2->_next;
while (_temp2 != nullptr) {
_temp1 = new Node<T>(_temp2->_data);
_temp1 = _temp1->_next;
_temp2 = _temp2->_next; //temp2 should be the next node after temp1
}
}
else
_head = nullptr;
}
return *this;
}
template <class T>
Stack<T>::~Stack() {
nullify();
}
template <class T>
void Stack<T>::nullify() {
while (!empty()) {
pop();
}
}
template <class T>
void Stack<T>::pop() {
if (empty()) {
throw range_error("Stack<T>::pop(): attempt to pop from an empty stack.");
}
Node<T>* tmpPtr = _head->_next;
delete _head;
_head = tmpPtr;
}
template <class T>
bool Stack<T>::empty() const {
return _head == nullptr;
}
template <class T>
void Stack<T>::push(const T& data) {
Node<T>* tmpPtr = new Node<T>(data);
tmpPtr->_next = _head;
_head = tmpPtr;
}
template <class T>
const T& Stack<T>::top() const {
if (empty()) {
throw range_error("Stack<T>::top(): attempt to read empty stack.");
}
return _head->_data;
}
template <class T>
void Stack<T>::dump() const {
Node<T>* nodePtr = _head;
while (nodePtr != nullptr) {
cout << nodePtr->_data << endl;
nodePtr = nodePtr->_next;
}
}
#endif
While pushing 34, 67, 92 it shows only 92 for the copy constructor during output. Here's the code for which I'm testing my .h code:
#include "stack.h"
#include <iostream>
using namespace std;
using std::cout;
using std::endl;
int main()
{
cout << "Testing default constructor\n";
Stack<int> intStack;
intStack.dump();
cout << "Stack is empty initially\n\n";
intStack.push(34);
intStack.push(67);
intStack.push(92);
cout << "Testing copy constructor after inserting 92, 67 & 34: \n";
Stack<int> test1(intStack);
//cout << "Dumping intStack into Test1 & displaying it: \n";
test1.dump();
cout << "\nTesting destructor: \n";
test1.nullify();
test1.dump();
cout << "Its empty\n\n";
Stack<int> test2;
test2.push(75);
test2.push(56);
test2.push(88);
test2.push(69);
cout << "Testing assignment operator after inserting 69, 88, 56 & 75: \n";
Stack<int> test3;
test3 = test2;
test3.dump();
cout << "\nTesting destructor: \n";
test2.nullify();
test2.dump();
cout << "Its empty\n\n";
return 0;
}
I'm still not used to C++ completely so sorry for any errors.
There are several things wrong with your Stack class.
First, the copy constructor doesn't initialize all the members, and neither does your default constructor. Those need to be fixed:
template <class T>
Stack<T>::Stack() : _head(nullptr), _temp1(nullptr), _temp2(nullptr) {}
template <class T>
Stack<T>::Stack(const Stack<T>& rhs) : _head(nullptr), _temp1(nullptr), _temp2(nullptr)
{
//...
}
Once this is done, the copy constructor can be easily implemented using your other existing function, Stack::push. Your implementation is way too complicated.
template <class T>
Stack<T>::Stack(const Stack<T>& rhs) : _head(nullptr), _temp1(nullptr), _temp2(nullptr) {
Node<T>* temp = rhs._head;
while (temp)
{
push(temp->_data);
temp = temp->_next;
}
}
What is being done here? Simple -- all we are doing is taking the head of the passed-in Stack, and looping over the items calling Stack::push to add the data to the new Stack object. Since you have a push function already coded, you should be using it.
Second, note that we use a local temp variable. I doubt you need any of those _temp members in your class, but that is a different story.
Last, your assignment operator can easily be implemented, given you have a copy constructor and destructor for Stack:
template <class T>
const Stack<T>& Stack<T>::operator=(const Stack<T>& rhs) {
if (this != &rhs) {
Stack<T> temp = rhs;
std::swap(temp._head, _head);
std::swap(temp._temp1, _temp1);
std::swap(temp._temp2, _temp2);
}
return *this;
}
That technique uses copy / swap. All that is being done is to create a temporary from the passed-in Stack object, and just swap out the current contents with the temporary's contents. Then the temporary dies off with the old contents.
Given all of this, the class should work correctly. Whether it is 100% correct with all of the other functions, that again is a different issue.
Edit:
Here is a fix for the copy constructor. Note we still use existing functions to make the copy:
template <class T>
Stack<T>::Stack(const Stack<T>& rhs) : _head(nullptr), _temp1(nullptr), _temp2(nullptr) {
Node<T>* temp = rhs._head;
Stack<T> tempStack;
while (temp)
{
tempStack.push(temp->_data);
temp = temp->_next;
}
while (!tempStack.empty())
{
push(tempStack.top());
tempStack.pop();
}
}
This is not as efficient, but usually a stack data structure uses an underlying container such as vector where it is easy to reverse the underlying contents, and not based on a singly linked-list as you're using.
When I will display the items in a queue I use the while loop
while (!queue.isEmptyQueue())
{
cout << queue.front() << " ";
queue.deleteQueue();
}
The items will be gone because of the deleteQueue() function so I cannot display it again.
How can I create a copy of the queue?
I tried the code below but it gives me errors.
queue1 = queue;
while (!queue1.isEmptyQueue())
{
cout << queue1.front() << " ";
queue1.deleteQueue();
}
I am using linkedQueue.h
#include<assert.h>
template <class Type>
struct nodeType
{
Type info;
nodeType<Type> *link;
};
template <class Type>
class linkedQueueType //: public queueADT<Type>
{
public:
const linkedQueueType<Type>& operator=(const linkedQueueType<Type>&);
bool isEmptyQueue() const;
bool isFullQueue() const;
void initializeQueue();
Type front() const;
Type back() const;
void addQueue(const Type& queueElement);
void deleteQueue();
linkedQueueType();
linkedQueueType(const linkedQueueType<Type>& otherQueue);
~linkedQueueType();
private:
nodeType<Type> *queueFront;
nodeType<Type> *queueRear;
};
template <class Type>
bool linkedQueueType<Type>::isEmptyQueue() const
{
return(queueFront == NULL);
}
template <class Type>
bool linkedQueueType<Type>::isFullQueue() const
{
return false;
}
template <class Type>
void linkedQueueType<Type>::initializeQueue()
{
nodeType<Type> *temp;
while (queueFront!= NULL)
{
temp = queueFront;
queueFront = queueFront->link;
delete temp;
}
queueRear = NULL;
}
template <class Type>
void linkedQueueType<Type>::addQueue(const Type& newElement)
{
nodeType<Type> *newNode;
newNode = new nodeType<Type>;
newNode->info = newElement;
newNode->link = NULL;
if (queueFront == NULL)
{
queueFront = newNode;
queueRear = newNode;
}
else
{
queueRear->link = newNode;
queueRear = queueRear->link;
}
}
template <class Type>
Type linkedQueueType<Type>::front() const
{
assert(queueFront != NULL);
return queueFront->info;
}
template <class Type>
Type linkedQueueType<Type>::back() const
{
assert(queueRear!= NULL);
return queueRear->info;
}
template <class Type>
void linkedQueueType<Type>::deleteQueue()
{
nodeType<Type> *temp;
if (!isEmptyQueue())
{
temp = queueFront;
queueFront = queueFront->link;
delete temp;
if (queueFront == NULL)
queueRear = NULL;
}
else
cout << "Cannot remove from an empty queue" << endl;
}
template<class Type>
linkedQueueType<Type>::linkedQueueType()
{
queueFront = NULL;
queueRear = NULL;
}
template <class Type>
linkedQueueType<Type>::~linkedQueueType()
{
initializeQueue();
}
If what you want to do is copy the queue, then a copy constructor / assignment operator is what you should have, as Martin said.
But if what you want is for the items to still be there after you go through the queue, then what your queue is missing is a way to tell how many items are in the queue.
You can cout each item and then move it to the back of the queue, that number of times.
Either way, all of these are missing for it to be a good queue implementation.
Copy constructor, assignment operator, size function.
(And technically, a queue doesn't have functionality to access the back item. So I wouldn't call this a queue with missing functionality, I would call it a linked list with missing functionality.)
Your problem is that your linkedQueueType doesn't have an assignment operator so the compiler is giving you one which just copies the pointers. You need an assignment operator which clones the elements.
I'm struggling with Implementing STL Double LinkedList. I'm almost a newbie with c++ and OOP programming, I've almost good knowledge of C language but all these new concepts are difficult to grasp and implement with data structure. I'm trying to make a good generic ADT following the STL style with iterator pattern and template.
There are no Syntax error, instead, there is a big logic problem with element insertion(pushFront function) that insert only the last element(check main function), I tried to debug but still can't find the problem. Hope that someone can help me :-)
These are my code snippet
Node class:
//Forward declaration
template<class T>
class LinkedList;
//Node should be structure?
template<class T>
class Node
{
friend class LinkedList<T>;
public:
Node(): pPrev_(nullptr), pNext_(nullptr) {}
Node(const T& value): data_(value), pPrev_(nullptr), pNext_(nullptr) {}
/*
* Implementing double linked list node
* data_: node's data of type T
* pNext_: pointer to the next node
* pPrev_: pointer to the previous node
*/
// if I put Private there some errors with private stuff, I have declared also LInkedList as friend
T data_;
Node<T>* pPrev_;
Node<T>* pNext_;
};
Iterator Class:
template<class T>
class ListIterator
{
// Declaring LinkedList friend class, now
//LinkedList can access to all data in this class
friend class LinkedList<T>;
public:
//Constructors
ListIterator();
ListIterator(Node<T>* node);
//Destructor
~ListIterator();
// Assignement Overload
//ListIterator<T> operator=(const)
//Deferencing Overload
T operator*();
//Prefix Overload
ListIterator<T> operator++();
ListIterator<T> operator--();
//Postfix Overload
ListIterator<T> operator++(int);
ListIterator<T> operator--(int);
//Relational Overload
bool operator==(const ListIterator<T>& Node);
bool operator!=( const ListIterator<T>& Node);
private:
// Actual node holden by iterator
Node<T>* curNode_;
};
/*
LIST_ITERATOR IMPLEMETATION
*/
template <class T>
ListIterator<T>::ListIterator(): curNode_(nullptr){}
template <class T>
ListIterator<T>::ListIterator(Node<T>* node): curNode_(node) {}
//Destructor
template <class T>
ListIterator<T>::~ListIterator() {}
//Deferencing Overload
template <class T>
T ListIterator<T>::operator *()
{
//Return the VALUE of the current node holden by iterator
return this->curNode_->data_;
}
//Prefix Overload
template <class T>
ListIterator<T> ListIterator<T>::operator ++()
{
/*
* Check if the next node is a valid node, then
* the current node will be the next node
* Return the value of the current node
*/
if (this->curNode_->pNext_ != nullptr)
this->curNode_ =this->curNode_->pNext_; //Like it++, jump to the next node
return *this;
}
template <class T>
ListIterator<T> ListIterator<T>::operator --()
{
/*
* Check if the previous node is a valid node, then
* the current node will be the previous node
* Return the value of the current node
*/
if( this->curNode_->pPrev_ != nullptr)
this->curNode_ = this->curNode_->pPrev;
return *this; //?? why return this
}
//Postfix Overload
template <class T>
ListIterator<T> ListIterator<T>::operator ++(int)
{
ListIterator<T> temp= *this;
++(*this);
return temp;
}
template <class T>
ListIterator<T> ListIterator<T>::operator --(int)
{
ListIterator<T> temp= *this;
--(*this);
return temp;
}
// Inequalities Overload
template <class T>
bool ListIterator<T>::operator==(const ListIterator<T>& node)
{
/*
* Check if the address of the current node is equal to the address of node param
*/
return( this->curNode_== node.curNode_);
}
template <class T>
bool ListIterator<T>::operator!=(const ListIterator<T>& node)
{
return !((*this) == node);
}
LinkedList Class:
template<class T>
class LinkedList
{
public:
typedef ListIterator<T> iterator;
//Constructors
LinkedList();
LinkedList(const LinkedList<T>& copyList);
//Destructor
~LinkedList();
//List Status Methods
bool isEmpty();
unsigned int getSize();
iterator begin();
iterator end();
//Should parameters be constant and passed by reference &? let's check with tester if there are some troubles
//Insert Methods
void pushFront(const T value);
void pushBack(const T value);
void insertAt(const T value,iterator& atPos);
//Remove Methods
void popFront();
void popBack();
void removeAt(iterator& pos);
void clear();
/** Addtional methods
*
* sort
* min,max,
* clear,
* overload <<
* print
*/
private:
/*
* Keeping a pointer to head and tail of the list;
* Size_: number of list's element
*/
Node<T>* Head_;
Node<T>* Tail_;
unsigned int Size_;
};
// LIST IMPLEMENTATION
// Constructors
template < class T>
LinkedList<T>::LinkedList()
{
/*
* Create a new empty node, head and tail are/share the same node at this step.
* Assign to head's pointer to next node NULL
* Assign to tail's pointer to previous node NULL
*/
this->Head_=this->Tail_= new Node<T>;
this->Head_->pNext_= nullptr;
this->Tail_->pPrev_= nullptr;
this->Size_=0;
}
// WIP TO CHECK
template <class T>
LinkedList<T>::LinkedList(const LinkedList<T>& list){
this->Head_=this->Tail_= new Node<T>;
this->Head_->pNext_= nullptr;
this->Tail_->pPrev_= nullptr;
this->Size_=0;
// create iterator to loop inside the container
for(iterator it= list.begin ; it != list.end(); it++)
this->pushBack(*it);
}
//Destructor
template <class T>
LinkedList<T>::~LinkedList()
{
this->clear(); //delete all nodes
delete this->Tail_;
}
//Begin & end()
template <class T>
ListIterator<T> LinkedList<T>::begin()
{
iterator it= this->Head_;
return it;
}
template <class T>
ListIterator<T> LinkedList<T>::end()
{
iterator it= this->Tail_;
return it;
}
//Clear
template< class T>
void LinkedList<T>::clear()
{
iterator it= this->begin();
while(it != this->end())
this->removeAt(it);
}
These are the methods that gives me error:
//Insert At
template <class T>
void LinkedList<T>::insertAt(const T value, iterator& atPos)
{
Node<T>* newNode= new Node<T>;
newNode->data_= value;
//Add links
if( atPos == this->begin())
{
newNode->pNext_=this->Head_;
this->Head_=newNode;
}
else if ( atPos == this->end())
//Still to implement
this->Tail_= newNode;
else
{
newNode->pNext_ = atPos.curNode_;
atPos.curNode_->pPrev_ = newNode;
atPos.curNode_->pPrev_->pNext_ = newNode;
newNode->pPrev_=atPos.curNode_->pPrev_;
}
atPos.curNode_= newNode;
this->Size_++;
}
template <class T>
void LinkedList<T>::pushFront(const T value)
{
iterator it= this->begin();
this->insertAt(value, it);
}
And here some lines to test the ADT:
#include <iostream>
#include <stdlib.h>
#include <string>
#include "LinkedList.h"
using namespace std;
int main() {
Node<int> nd(4);
ListIterator<int> it;
LinkedList<int> lst;
for(int i=0; i < 25;i++)
lst.pushFront(i);
for(it=lst.begin(); it != lst.end();it++)
{
cout << *it << endl;
system("Pause");
}
cout << "iia";
system("Pause");
return 0;
}
There are no errors in your output:
24
Press any key to continue . . .
23
Press any key to continue . . .
22
Press any key to continue . . .
...
Press any key to continue . . .
0
Press any key to continue . . .
iiaPress any key to continue . . .
P.S. don't use this where you can avoid it. Code will be easier for reading.
I am attempting to make a queue in c++ using a double linked list. I Have not fully tested everything since i am stuck at the step where you dequeue. I attempted to create a temp node, and move around stuff so when I call delete on the head node in the queue (called queue), and then set the head to a temp node which is the next element, (you can see in the code) but when I call delete, is where it crashes, according to MS Visual studios 2013. Also to add how weird this is, following the stack called, after delete is called, setPrev is called and set the prev node and crashes there. Now I never call this function during any of my destructors deletes so any help will do. I will try my best to understand any answers but I am still new to c++ terminology. Below is my code. Oh one last thing, in main, all I did was call enqueue once, then dequeue once, then delete
Node Class
...
#ifndef TSDNODE_H
#define TSDNODE_H
template <class T>
class DNode
{
private:
DNode<T>* next;
DNode<T>* prev;
T data;
public:
DNode(T);
void setNext(DNode<T>* next);
void setPrev(DNode<T>* prev);
DNode<T>* getNext() const;
DNode<T>* getPrev() const;
T getData() const;
void setData(T data);
~DNode();
};
template <class T>
DNode<T>::DNode(T data)
{
this->next = nullptr;
this->data = data;
this->prev = nullptr;
}
template <class T>
void DNode<T>::setNext(DNode<T>* next)
{
this->next = next;
}
template <class T>
void DNode<T>::setPrev(DNode<T>* prev)
{
this->prev = prev;
}
template <class T>
DNode<T>* DNode<T>::getNext() const
{
return this->next;
}
template <class T>
DNode<T>* DNode<T>::getPrev() const
{
return this->prev;
}
template <class T>
T DNode<T>::getData() const
{
return this->data;
}
template <class T>
void DNode<T>::setData(T data)
{
this->data = data;
}
template <class T>
DNode<T>::~DNode()
{
delete this->next;
delete this->prev;
this->next = nullptr;
this->prev = nullptr;
}
#endif /* TSDNODE_H */
....
Queue Class
....
#ifndef TSQUEUE_H
#define TSQUEUE_H
#include "TSDNode.h"
#include <string>
template <class T>
class Queue
{
private:
DNode<T>* queue;
DNode<T>* tail;
int size;
public:
Queue();
void enqueue(T data);
T dequeue();
~Queue();
};
template <class T>
Queue<T>::Queue()
{
this->queue = nullptr;
this->tail = this->queue;
size = 0;
}
template <class T>
void Queue<T>::enqueue(T data)
{
if (this->tail != NULL)
{
this->tail->setNext(new DNode<T>(data));
this->tail->getNext()->setPrev(this->tail);
this->tail = this->tail->getNext();
}
else
{
this->queue = new DNode<T>(data);
this->tail = this->queue;
}
size++;
}
template <class T>
T Queue<T>::dequeue()
{
T data;
if (this->queue == nullptr)
{
delete this->tail;
delete this->queue;
this->tail = nullptr;
std::string ex = "Exception: Empty Queue\n";
throw ex;
}
else if (this->queue != nullptr)
{
data = this->queue->getData();
DNode<T>* node = this->queue->getNext();
this->queue->setNext(nullptr);
this->queue->setPrev(nullptr);
node->setPrev(nullptr);
//--------------------------------------------------- crashes here
delete this->queue;
this->queue = node;
}
size--;
return data;
}
template <class T>
Queue<T>::~Queue()
{
delete this->queue;
this->queue = nullptr;
this->tail = nullptr;
}
#endif /* TSQUEUE_H */
In your DNode destructor, you don't want to delete the next and prev nodes. You only want to delete this node, not everything it links to.
Remove these lines
delete this->next;
delete this->prev;
Edit: Actually this isn't your problem, because you are clearing out the next and prev values before you delete the node. I still think it is better to not automatically delete the whole chain, but as long as you are consistent with how you handle node deletion it should still work.
You actually problem is that when you dequeue the last node, you still try to set the next pointer of the next node in this line:
node->setPrev(nullptr);
//--------------------------------------------------- crashes here
At this point node is nullptr, so trying to access node->next causes a crash. A simple if test is all you need
if (node != nullptr)
node->setPrev(nullptr);
//--------------------------------------------------- no longer crashes here
Edit 2:
Also note that in the case where the next node in the queue is nullptr, you also want to set the tail to nullptr.
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.