Today i'm praticing deleting a node implementation in LinkedList and this problem occur. This is my LinkedList.h file:
#pragma once
template <class Data>
class Node
{
public:
Node();
Node(Data newData, Node<Data>* newNext);
~Node();
Node<Data>* next;
Data data;
};
template<class Data>
class LinkedList
{
public:
LinkedList();
~LinkedList();
int size();
bool put(Data data,int pos);
bool del(int pos);
void show();
private:
typedef Node<Data>* nodePtr;
nodePtr head;
int N;
bool isEmpty();
nodePtr getPosition(int pos);
};
Then my LinkedList.cpp file:
#include <iostream>
#include "LinkedList.h"
using namespace std;
template<class Data>
Node<Data>::Node() {
next = NULL;
}
template<class Data>
Node<Data>::Node(Data newData, Node * newNext)
{
data = newData;
next = newNext;
}
template<class Data>
Node<Data>::~Node()
{
delete next;
}
template<class Data>
LinkedList<Data>::LinkedList() {
head = NULL;
N = 0;
}
template<class Data>
LinkedList<Data>::~LinkedList()
{
delete head;
}
template<class Data>
int LinkedList<Data>::size()
{
return N;
}
template<class Data>
bool LinkedList<Data>::isEmpty()
{
return N == 0;
}
template<class Data>
Node<Data>* LinkedList<Data>::getPosition(int pos)
{
nodePtr temp = head;
if (pos > N-1) pos = N-1;
for (int i = 0; i < pos; i++)
temp = temp->next;
return temp;
}
template<class Data>
bool LinkedList<Data>::put(Data data, int pos)
{
nodePtr add;
if (pos == 0) {
add = new Node<Data>(data, head);
head = add;
}
else{
nodePtr pPre = getPosition(pos-1);
nodePtr pCur = pPre->next;
add = new Node<Data>(data, pCur);
pPre->next = add;
}
N++;
return true;
}
template<class Data>
bool LinkedList<Data>::del(int pos)
{
if (isEmpty()) return false;
if (pos == 0) {
nodePtr pTemp = head;
head = head->next;
delete pTemp; //error
}
else {
nodePtr pPre = getPosition(pos - 1);
nodePtr pCur = pPre->next;
pPre->next = pCur->next;
delete pCur; //error
}
N--;
return true;
}
template<class Data>
void LinkedList<Data>::show()
{
for (nodePtr pTemp = head; pTemp != NULL; pTemp = pTemp->next)
cout << pTemp->data;
}
void main() {
LinkedList<int> list;
list.put(0, 0);
list.put(1, 0);
list.put(2, 0);
list.put(3, 0);
list.put(4, 0);
list.del(0);
list.show();
}
the program works if i comment these line (but i think it'll lead to memory leak), if i let these line there it cause "program has stopped working" and a random number in console window.
So can you guys please help me how to delete these pointer in correctly way?
Sorry for previous ambiguous question.
Sorry for my bad English.
Oh i just firgure out my mistake. Because of my ~Node() method here:
template<class Data>
Node<Data>::~Node()
{
delete next;
}
so when i delete a Node, it delete all pointer it linked to in a row, causing that error. Anyway thanks for helping guys.
Related
I have written a linked list based queue, where each node is linked to the node behind it in the queue. Every other function in the program works with no problems. For some reason this destructor is giving me some issues, and I am not sure why.
I am getting this error:
Exception thrown: read access violation.
temp was 0xCDCDCDCD.
Thanks for any help given.
#pragma once
#include <iostream>
#include "Node.h"
template <typename T>
class LQueue
{
Node<T>* front;
Node<T>* end;
int length;
public:
LQueue();
~LQueue();
//Add item into queue
void enqueue(T x);
//Remove item from front of queue
void dequeue();
//return item at front of queue
T peek();
//Is queue empty?
bool isEmpty();
int getLength() { return length; }
};
template<typename T>
inline LQueue<T>::LQueue()
{
front = nullptr;
end = nullptr;
length = 0;
}
template<typename T>
inline void LQueue<T>::enqueue(T x)
{
Node<T>* temp = new Node<T>;
temp->data = x;
length++;
if (isEmpty())
{
temp->next = nullptr;
front = temp;
end = temp;
}
else
{
end->next = temp;
end = temp;
}
}
template<typename T>
inline void LQueue<T>::dequeue()
{
if (isEmpty())
{
std::cout << "\n[!] Empty Queue, Nothing To Remove.\n";
return;
}
if (end == front)
{
delete front;
front = nullptr;
end = nullptr;
}
else
{
Node<T>* temp = front->next;
delete front;
front = temp;
}
length--;
}
template<typename T>
inline T LQueue<T>::peek()
{
return front->data;
}
template<typename T>
inline bool LQueue<T>::isEmpty()
{
if (front == nullptr)
return true;
else
return false;
}
template<typename T>
inline LQueue<T>::~LQueue()
{
Node<T>* temp = front;
while (temp != nullptr)
{
Node<T>* temp2 = temp;
temp = temp->next;
delete temp2;
}
}
Error from visual studios
Thanks to #Yksisarvinen, I have fixed my problem.
The end->next was only initialized if the queue was empty. I didn't initialize end->next if queue wasn't empty.
Old Code
template<typename T>
inline void LQueue<T>::enqueue(T x)
{
Node<T>* temp = new Node<T>;
temp->data = x;
length++;
if (isEmpty())
{
temp->next = nullptr;
front = temp;
end = temp;
}
else
{
end->next = temp;
end = temp;
}
}
New Code:
template<typename T>
inline void LQueue<T>::enqueue(T x)
{
Node<T>* temp = new Node<T>;
temp->data = x;
length++;
temp->next = nullptr;
if (isEmpty())
{
front = temp;
end = temp;
}
else
{
end->next = temp;
end = temp;
}
}
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
so I have an assignment where I need to create a doubly linked list and then create a stack and queue class and inherit from the linkedlist class in order to create an RPN calculator. So far I have created my doubly linkedlist class and the other to classes. However, I am having trouble understanding how I will inherit and use the linked list class with the stack and queue. I will provide what I have so far.
I have gone to tutoring and have not had much help so I thought I would look for some extra help, do not want homework done for me but to just be pointed in the right direction.
Stack.h
using std::iterator;
using std::vector;
using std::string;
template<class T>
class Stack : public vector<T>
{
private:
T getElement(bool erase);
typename std::vector<T> ::iterator pEnd;
T top;
public:
Stack();
T pop();
T peek();
void push(T elem);
};
template<class T>
Stack<T>::Stack()
{
}
template<class T>
void Stack<T>::push(T elem)
{
this->push_back(elem);
}
template<class T>
T Stack<T>::peek()
{
return this->getElement(false);
}
template<class T>
T Stack<T>::pop()
{
return this->getElement(true);
}
template<class T>
T Stack<T>::getElement(bool erase)
{
this->pEnd = this->end() - 1;
T tmp;
if (this->size() > 0)
{
tmp = *this->pEnd;
if (erase) {
this->erase(pEnd);
}
}
return tmp;
}
Queue.h
using namespace std;
class Queue
{
private:
int items[MAXQUEUE];
int head;
int tail;
public:
Queue();
bool isEmpty();
bool isFull();
bool enqueue(int item);
int dequeue();
int peek();
};
Queue::Queue()
:head(QEMPTY), tail(QEMPTY)
{
}
bool Queue::isEmpty()
{
return this->head == this->tail;
}
bool Queue::isFull()
{
return this->tail == MAXQUEUE;
}
bool Queue::enqueue(int item)
{
if (this->isFull())
return false;
this->items[this->tail] = item;
tail = (tail + 1) % MAXQUEUE;
return true;
}
int Queue::dequeue()
{
if (this->isEmpty())
return EMPTY;
int item = this->items[head];
this->head = (this->head + 1) % MAXQUEUE;
return item;
}
int Queue::peek() {
return this->tail;
}
doublylinkedlist.h
using std::iterator;
using std::vector;
using std::string;
/*START OF NODE CLASS*/
/*---------------------------------------------*/
template<class T>
struct Node
{
T Data;
T Search;
T value;
Node<T>*Next;
Node<T>*Prev;
};
template<class T>
class LinkedList
{
private:
Node<T> *Head;
public:
LinkedList();
void addNode(T Data);
void deleteNode(T Search);
void insert(T Search, T value);
void printListBackwards();
void printListForwards();
};
template<class T>
LinkedList<T>::LinkedList()
{
this->Head = NULL;
}
template<class T>
void LinkedList<T>::addNode(T data)
{
if (Head == NULL)
{
Head = new Node<T>;
Head->Data = data;
Head->Next = NULL;
Head->Prev = NULL;
}
else
{
Node<T>*p = this->Head;
while (p->Next != NULL)
p = p->Next;
Node<T>*n = new Node<T>;
n->Data = data;
n->Next = NULL;
p->Next = n;
n->Prev = p;
}
}
template<class T>
void LinkedList<T>::insert(T Search, T value)
{
Node *p = Head;
while (p->Data != Search)
{
p = p->Next;
}
Node *n = new Node;
n->Data = value;
n->Next = p->Next;
p->Next = n;
}
template<class T>
void LinkedList<T>::deleteNode(T Search)
{
Node *p = Head;
while (p->Next->Data != Search)
{
p = p->Next;
}
Node *delPtr = p->Next;
p->Next = p->Next->Next;
delete delPtr;
}
template<class T>
void LinkedList<T>::printListBackwards()
{
Node<T> *p = Head;
while (p->Next != NULL)
{
p = p->Next;
}
while (p != NULL)
{
cout << p->Data<< endl;
p = p->Prev;
}
}
template<class T>
void LinkedList<T>::printListForwards()
{
Node<T> *p = Head;
while (p != NULL)
{
cout << p->Data << endl;
p = p->Next;
}
}
A doubly linked list can be added to at the head or the tail, and removed at the tail.
A stack pushes at one end (the head?) and pops at the same end (the head).
A queue pushes at one end (the tail) and pops at the other end (the head).
I'm trying to create a basic singly-linked list using a separate Node class and LinkedList class. I barely know what I'm doing as I've just started learning C++, so any help would be greatly appreciated.
The LinkedList part of the code runs on its own, but I'm sure there are some corrections to be made there too. My main problem is that, when trying to add to the linked list, I'm getting (at line 64 of LinkedList.h):
Exception thrown: read access violation. this->head was nullptr.
I'm using Microsoft Visual Studio 2015. Here's the code:
LinkedList.h (it's inline):
#pragma once
#include <iostream>
using namespace std;
class Node
{
private:
Node *next = NULL;
int data;
public:
Node(int newData) {
data = newData;
next = NULL;
}
Node() {
}
~Node() {
if(next)
delete(next);
}
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
void setNext(Node newNext) {
*next = newNext;
}
Node getNext() {
return *next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
{
head = NULL;
size = 0;
}
~LinkedList()
{
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, *head);
++size;
}
int remove()
{
if (size == 0) {
return 0;
}
else {
*head = (*head).getNext();
--size;
return 1;
}
}
int remove(int numberToRemove)
{
if (size == 0)
return 0;
Node *currentNode = head;
for (int i = 0; i < size; i++) {
if ((*currentNode).getData() == numberToRemove) {
*currentNode = (*currentNode).getNext();
return 1;
}
}
}
void print()
{
if (size == 0) {
return;
}
else {
Node currentNode = *head;
for (int i = 0; i < size; i++) {
cout << currentNode.getData();
currentNode = currentNode.getNext();
}
cout << endl;
}
}
};
List Tester.cpp
// List Tester.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "LinkedList.h"
using namespace std;
int main()
{
LinkedList myList;
myList.add(4);
system("pause");
}
You are making copies where you should not:
This:
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
should be:
Node(int newData, Node* newNext) {
data = newData;
next = newNext;
}
Because now this:
head = new Node(numberToAdd, *head);
becomes this:
head = new Node(numberToAdd, head);
and will work even if head is a null pointer. You may need to adjust your other code accordingly.
Your whole implementation is full of errors. It should look more like this instead:
#pragma once
#include <iostream>
class Node
{
private:
int data;
Node *next;
public:
Node(int newData, Node *newNext = NULL)
: data(newData), next(newNext)
{}
void setNext(Node *newNext) {
next = newNext;
}
Node* getNext() {
return next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
: head(NULL), size(0)
{
}
~LinkedList()
{
Node *currentNode = head;
while (currentNode)
{
Node *nextNode = currentNode->getNext();
delete currentNode;
currentNode = nextNode;
}
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, head);
++size;
}
bool remove()
{
Node *currentNode = head;
if (!currentNode)
return false;
head = currentNode->getNext();
delete currentNode;
--size;
return true;
}
bool remove(int numberToRemove)
{
Node *currentNode = head;
Node *previousNode = NULL;
while (currentNode)
{
if (currentNode->getData() == numberToRemove)
{
if (head == currentNode)
head = currentNode->getNext();
if (previousNode)
previousNode->setNext(currentNode->getNext());
delete currentNode;
return true;
}
previousNode = currentNode;
currentNode = currentNode->getNext();
}
return false;
}
void print()
{
Node *currentNode = head;
if (!currentNode) return;
do
{
std::cout << currentNode->getData();
currentNode = currentNode->getNext();
}
while (currentNode);
std::cout << std::endl;
}
};
Which can then be simplified using the std::forward_list class (if you are using C++11 or later):
#pragma once
#include <iostream>
#include <forward_list>
#include <algorithm>
class LinkedList
{
private:
std::forward_list<int> list;
public:
void add(int numberToAdd)
{
list.push_front(numberToAdd);
}
bool remove()
{
if (!list.empty())
{
list.pop_front();
return true;
}
return false;
}
bool remove(int numberToRemove)
{
std::forward_list<int>::iterator iter = list.begin();
std::forward_list<int>::iterator previous = list.before_begin();
while (iter != list.end())
{
if (*iter == numberToRemove)
{
list.erase_after(previous);
return true;
}
++previous;
++iter;
}
return false;
}
void print()
{
if (list.empty()) return;
std::for_each(list.cbegin(), list.cend(), [](int data){ std::cout << data });
std::cout << std::endl;
}
};
I've gone through a bunch of threads trying to understand what is going on exactly with linked lists and bubblesort, and I think I get the bulk of it.
Right now my program is simply crashing when I get to the sort function and I am not sure why. Hopefully another set of eyes will see what I do not.
Any help is greatly appreciated.
DoublyList.h:
#include "listNode.h"
#ifndef DOUBLYLIST_H
#define DOUBLYLIST_H
template <typename T>
class DoublyList
{
public:
DoublyList();
~DoublyList();
void addFront(T d);
void addBack(T d);
T removeFront();
T removeBack();
T peak();
bool isEmpty();
int getSize();
void printList();
void sortList();
private:
ListNode<T> *front;
ListNode<T> *back;
int numOfElements;
};
template <typename T>
DoublyList<T>::DoublyList(){
front = NULL;
back = NULL;
numOfElements = 0;
}
template <typename T>
DoublyList<T>::~DoublyList(){
if(numOfElements!=0){
ListNode<T> *current;
current = front;
while (current != back)
{
ListNode<T> *temp = current;
current = current->next;
temp->next = NULL;
temp->prev = NULL;
delete temp;
numOfElements--;
}
//at this point current = back, now delete it
current->next = NULL;
current->prev = NULL;
delete current;
numOfElements--;
}
//this is a safeguard if you create a LL and then delete it without doing anything to it
else{
cout<<"deleted empty LL"<<endl;
delete front;
delete back;
}
}
template <typename T>
void DoublyList<T>::addFront(T d)
{
ListNode<T> *node = new ListNode<T>();
node->data = d;
if (isEmpty()){
back = node;
}
else{
front->prev = node;
}
node->next = front;
front = node;
++numOfElements;
}
template <typename T>
T DoublyList<T>::removeFront()
{
if (isEmpty()){
return T();
}
else
{
ListNode<T>* temp = front;
if (front->next == 0){
back = 0;
}
else
{
front->next->prev = 0;
}
front = front->next;
temp->next = 0;
T theData = temp->data;
delete temp;
--numOfElements;
return theData;
}
}
template <typename T>
void DoublyList<T>::addBack(T d)
{
ListNode<T> *node = new ListNode<T>();
node->data = d;
if (isEmpty()){
front = node;
}
else{
back->next = node;
}
node->prev = back;
back = node;
++numOfElements;
}
template <typename T>
T DoublyList<T>::removeBack()
{
if (isEmpty()) {
return T();
}
else
{
ListNode<T>* temp;
temp = back;
if (back->prev == 0){
front = 0;
}
else{
back->prev->next = 0;
}
back = back->prev;
temp->prev = 0;
T theData = temp->data;
delete temp;
--numOfElements;
return theData;
}
}
template <typename T>
T DoublyList<T>::peak()
{
if (isEmpty()) {
return T();
}
return front->data;
}
template <typename T>
int DoublyList<T>::getSize(){
return numOfElements;
}
template <typename T>
bool DoublyList<T>::isEmpty(){
if(numOfElements == 0){
return true;
}
else{
return false;
}
}
template <typename T>
void DoublyList<T>::printList(){
if(numOfElements!=0){
ListNode<T> *current = front;
while(current!=back)
{
cout<<current->data<<endl;
current = current->next;
}
cout<<back->data<<endl;
}
else{
cout<<"list is empty"<<endl;
}
}
template <typename T>
void DoublyList<T>::sortList(){
int size = getSize();
ListNode<T> *current;
ListNode<T> *dummy;
ListNode<T> *next;
if(current == NULL) return;
if(current -> next == NULL) return;
int swapped = 1;
while(swapped){
swapped = 0; //last pass unless there is a swap
while(current -> next != NULL){
if(current-> data < current -> next -> data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
dummy -> data = current -> data;
current -> data = current -> next -> data;
current -> next -> data = dummy -> data;
}
current = current -> next;
}
}
}
#endif
listNode.h:
#include <iostream>
#ifndef LISTNODE_H
#define LISTNODE_H
using namespace std;
template <typename T>
class ListNode
{
public:
T data;//the data that we will store
ListNode();
ListNode(int d);
~ListNode();
ListNode *next;//int and ptr and the member variables
ListNode *prev;
};
template <typename T>
ListNode<T>::ListNode(int d){
data = d;
next = NULL;
prev = NULL;
}
template <typename T>
ListNode<T>::ListNode(){}
template <typename T>
ListNode<T>::~ListNode(){
delete next;
delete prev;
cout<<"deleted Node"<<endl;
}
#endif
testList.cpp
#include <iostream>
#include "doublyList.h"
#include "genericQueue.h"
int main(){
DoublyList<int> testQueue;
testQueue.addBack(3);
testQueue.addBack(5);
testQueue.addBack(2);
testQueue.addBack(10);
testQueue.addBack(1);
cout << "Before Sort: " << endl;
testQueue.printList();
cout << "After Sort: " << endl;
testQueue.sortList();
testQueue.printList();
}
The erors I could find so far are:
Your default ListNode() constructor doesn't null the next and prev pointers.
In void DoublyList<T>::sortList() you don't initialize dummy, so it just points into nowhere. Actually there is no reason to use a node list at all, you can just directly use a variable of type T.
You don't initialize current in the same function and you actually should reset current to e.g. front at the beginning of each outer loop.
You don't use next at all (and don't need to), so just remove it.
To sum it up, this is what void DoublyList<T>::sortList() could look like:
template <typename T>
void DoublyList<T>::sortList(){
int size = getSize();
ListNode<T> *current=front;
T dummy;
if (current == NULL) return;
if (current->next == NULL) return;
int swapped = 1;
while (swapped){
current = front;
swapped = 0; //last pass unless there is a swap
while (current->next != NULL){
if (current->data < current->next->data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
dummy = current->data;
current->data = current->next->data;
current->next->data = dummy;
}
current = current->next;
}
}
}
and this is my suggestion for the ListNode constructor.
template <typename T>
ListNode<T>::ListNode() :
next(nullptr),
prev(nullptr),
data{}
{}
Besides that, I also agree with DaveB that swapping pointers is the approach you should actually use.
To start with you need to initialize current in your sort function,
current = first;
template <typename T>
void DoublyList<T>::sortList(){
ListNode<T> *current;
ListNode<T> *next;
T tmp;
current = front;
if(current == NULL) return;
if(current -> next == NULL) return;
int swapped = 1;
while(swapped){
swapped = 0; //last pass unless there is a swap
while(current->next != nullptr){
if(current->data < current->next->data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
tmp = current->data;
current->data = current->next->data;
current->next->data = tmp;
}
current = current -> next;
}
if (swapped) // go back to start of list for next pass
current = front;
}
}