This is a very simple program that implements a stack using a linked list. Kindly help me figure out the logical bug that makes the program crash on run.
class LLStack {
public:
struct Node {
int data;
Node* next;
Node(int n) {
data = n;
next = 0;
}
Node(int n, Node* node) {
data = n;
next = node;
}
};
LLStack();
LLStack(const LLStack&);
LLStack& operator = (const LLStack&);
~LLStack();
void push(int);
int pop();
int top();
bool isEmpty();
void flush();
private:
Node* head;
};
LLStack::LLStack() {
head = 0;
}
LLStack::LLStack(const LLStack& s) {
head = new Node(NULL);
head->data = s.head->data;
head->next = new Node(*(s.head->next));
}
LLStack::~LLStack() {
this->flush();
}
LLStack& LLStack::operator = (const LLStack& s) {
this->head = new Node(NULL);
this->head->data = s.head->data;
this->head->next = new Node(*(s.head->next));
return *this;
}
void LLStack::push(int x) {
if (head == 0) head = new Node(x);
else {
Node* temp = new Node(x, head);
head = temp;
}
}
int LLStack::pop() {
if (head == 0) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
else {
Node* temp = head;
int n = temp->data;
head = temp->next;
delete temp;
return n;
}
}
int LLStack::top() {
if (head == 0) {
cout << "\n\nNo elements in the stack\n\n";
return -1;
}
else {
return head->data;
}
}
bool LLStack::isEmpty() {
return (head == 0);
}
void LLStack::flush() {
if (head == 0) {
cout << "\n\nNo elements in the Stack to flush\n\n";
return;
}
cout << "\n\nFlushing the Stack: ";
Node* temp = 0;
while (head != 0) {
temp = head;
cout << temp->data << " ";
head = head->next;
delete temp;
}
cout << endl << endl;
}
This is the trouble-maker fuction:
void reverseStack(LLStack& s1) {
LLStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
}
int main() {
LLStack s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
reverseStack(s);
cout << "\n\nFlushing s:\n";
s.flush();
system("pause");
return 0;
}
I have implemented my own copy constructor and the copy assignment operator. I don't understand why it crashes on run. On flushing it displays garbage values before crashing.
The problem is your copy assignment operator. Consider:
void reverseStack(LLStack& s1) {
LLStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
}
Everything works fine until you return from the function, at which point the destructor for s2 is called. The destructor calls flush(), which deletes all stack elements of s2. In your copy assignment operator (and copy constructor, at that), you create two nodes: head and head->next; the rest of the nodes are shared between the two stacks, so after s2 has been deleted, s1.head->next->next points to a node that has been deleted, but you still try to access it.
The solution is to have the copy assignment operator (and the copy constructor) create a proper deep copy of the stack, not just the first two elements, like this (also takes care of self assignment):
LLStack& LLStack::operator=(const LLStack& s) {
if (this==&s) return *this; // self assignment
flush(); // avoid memory leak
head = new Node(*s.head);
Node* s_ptr = s.head;
Node* t_ptr = head;
while (s_ptr->next) {
t_ptr->next = new Node(*s_ptr->next);
s_ptr = s_ptr->next;
t_ptr = t_ptr->next;
}
return *this;
}
Remember that the copy constructor should do the same.
Related
#include <iostream>
using namespace std;
template <typename Object>
struct Node
{
Object data;
Node* next;
Node(const Object &d = Object(), Node *n = (Object)NULL) : data(d), next(n) {}
};
template <typename Object>
class singleList
{
public:
singleList() { init(); }
~singleList() { eraseList(head); }
singleList(const singleList &rhs)
{
eraseList(head);
init();
*this = rhs;
print();
contains(head);
}
void init()
{
theSize = 0;
head = new Node<Object>;
head->next = (Object)NULL;
}
void eraseList(Node<Object> *h)
{
Node<Object> *ptr = h;
Node<Object> *nextPtr;
while (ptr != (Object)NULL)
{
nextPtr = ptr->next;
delete ptr;
ptr = nextPtr;
}
}
int size()
{
return theSize;
}
void print()
{
int i;
Node<Object> *current = head;
for(i=0; i < theSize; ++i){
cout << current->data << " ";
current = current->next;
}
}
bool contains(int x)
{
Node<Object> *current = head;
for (int i = 0; i < theSize; ++i){
if (current->data == x){
return true;
}
current = current -> next;
}
return false;
}
bool add(Object x){
if(!contains(x)){
Node<Object> *new_node = new Node<Object>(x);
new_node->data = x;
new_node->next = head;
head = new_node;
//head->next = new_node;
theSize++;
return true;
}
return false;
}
bool remove(int x)
{
if(contains(x)){
Node<Object> *temp = head;
Node<Object> *prev = NULL;
if(temp != NULL && temp ->data == x){
head = temp->next;
delete temp;
return 0;
}else{
while(temp != NULL && temp->data != x){
prev = temp;
temp = temp->next;
}
if(temp ==NULL){
return 0;
}
prev->next = temp->next;
delete temp;
}
return true;
//theSize--;
}
return false;
}
private:
Node<Object> *head;
int theSize;
};
int main()
{
singleList<int> *lst = new singleList<int>();
lst->add(10);
lst->add(12);
lst->add(15);
lst->add(6);
lst->add(3);
lst->add(8);
lst->add(3);
lst->add(18);
lst->add(5);
lst->add(15);
cout << "The original linked list: ";
lst->print();
cout << endl;
lst->remove(6);
lst->remove(15);
cout << "The updated linked list: ";
lst->print();
cout << endl;
cout << "The number of node in the list: " << lst->size() << endl;
return 0;
}
so the output is supposed to be the following:
The original linked list: 5 18 8 3 6 15 12 10
The update linked list: 5 18 8 3 12 10
The number of node in the list: 6
my output gives the original linked list part but then gives a segmentation fault (core dumped) error. I am not sure where my code is wrong but i think it is in my remove().
Some help will definitely be appreciated.
on line 109 i needed to decrement size.
bool remove(int x)
{
if(contains(x)){
Node<Object> *temp = head;
Node<Object> *prev = NULL;
if(temp != NULL && temp ->data == x){
head = temp->next;
delete temp;
return 0;
}else{
while(temp != NULL && temp->data != x){
prev = temp;
temp = temp->next;
}
if(temp ==NULL){
return 0;
}
prev->next = temp->next;
delete temp;
theSize--;
}
return true;
//theSize--;
}
return false;
}
Answer after second update:
had to fix the remove()
#include <iostream>
using namespace std;
template <typename Object>
struct Node
{
Object data;
Node* next;
Node(const Object &d = Object(), Node *n = (Object)NULL) : data(d), next(n) {}
};
template <typename Object>
class singleList
{
public:
singleList() { init(); }
~singleList() { eraseList(head); }
singleList(const singleList &rhs)
{
eraseList(head);
init();
*this = rhs;
print();
contains(head);
}
void init()
{
theSize = 0;
head = new Node<Object>;
head->next = (Object)NULL;
}
void eraseList(Node<Object> *h)
{
Node<Object> *ptr = h;
Node<Object> *nextPtr;
while (ptr != (Object)NULL)
{
nextPtr = ptr->next;
delete ptr;
ptr = nextPtr;
}
}
int size()
{
return theSize;
}
void print()
{
int i;
Node<Object> *current = head;
for(i=0; i < theSize; ++i){
cout << current->data << " ";
current = current->next;
}
}
bool contains(int x)
{
Node<Object> *current = head;
for (int i = 0; i < theSize; ++i){
if (current->data == x){
return true;
}
current = current -> next;
}
return false;
}
bool add(Object x){
if(!contains(x)){
Node<Object> *new_node = new Node<Object>(x);
new_node->data = x;
new_node->next = head;
head = new_node;
//head->next = new_node;
theSize++;
return true;
}
return false;
}
bool remove(int x){
Node<Object> *pCur = head;
Node<Object> *pPrev = pCur;
while (pCur && pCur->data != x) {
pPrev = pCur;
pCur = pCur->next;
}
if (pCur==nullptr) // not found
return false;
if (pCur == head) { // first element matches
head = pCur->next;
} else {
pPrev->next = pCur->next;
}
// pCur now is excluded from the list
delete pCur;
theSize--;
return true;
}
private:
Node<Object> *head;
int theSize;
};
int main()
{
singleList<int> *lst = new singleList<int>();
lst->add(10);
lst->add(12);
lst->add(15);
lst->add(6);
lst->add(3);
lst->add(8);
lst->add(3);
lst->add(18);
lst->add(5);
lst->add(15);
cout << "The original linked list: ";
lst->print();
cout << endl;
lst->remove(6);
lst->remove(15);
cout << "The updated linked list: ";
lst->print();
cout << endl;
cout << "The number of node in the list: " << lst->size() << endl;
return 0;
}
hope you're all doing well
im working on an assignment and i've been stuck here at this point for ages, and there are no errors or warnings in my code i dunno whats wrong. I'd appreciate the help
i checked all the pointers and null related things and still i couldnt find out what was wrong
#pragma once
#include<iostream>
using namespace std;
struct Node {
public:
int coefficient;
int power;
Node* Next;
int getcoefficient()
{
return this->coefficient;
}
int getpower()
{
return this->power;
}
};
class Polynomial {
private:
Node* Head;
Node* Tail;
public:
Polynomial();
int getco();
int getpow();
Polynomial(int arraycoefficients[], int arraypower[], int n);
~Polynomial();
void insert(int coefficient1, int power1);
void remove(int power1);
double Evaluate(double value);
Polynomial operator+(Polynomial O2);
/*Polynomial& operator=(Polynomial& p);*/
int degree()const;
void merge(Polynomial p);
void removeAll();
friend istream& operator>>(istream& in, Polynomial& P);
friend ostream& operator<<(ostream& out, const Polynomial& P);
};
and this is the cpp for the header file
#include "Polynomial.h"
#include<math.h>
#include <iostream>
using namespace std;
Polynomial::Polynomial()
{
Head = Tail = NULL;
}
int Polynomial::getco()
{
return Head->coefficient;
}
int Polynomial::getpow()
{
return Head->power;
}
Polynomial::Polynomial(int arraycoefficients[], int arraypower[], int n)
{
Head = NULL;
Tail = NULL;
for (int i = 0; i < n; i++) {
insert(arraycoefficients[i], arraypower[i]);
}
}
Polynomial::~Polynomial()
{
removeAll();
}
void Polynomial::insert(int coefficient1, int power1)
{
Node* node = new Node;
node->coefficient = coefficient1;
node->power = power1;
node->Next = NULL;
if (Head == NULL) {
Head = Tail = node;
return;
}
//addition at head
if (power1 == Head->power) {
Head->coefficient = Head->coefficient + coefficient1;
return;
}
//insert at head
if (power1 < Head->power) {
node->Next = Head;
Head = node;
return;
}
Node* temporary = Head;
while (temporary->Next != NULL) {
if (temporary->power == power1) {
temporary->coefficient = temporary->coefficient + coefficient1;
return;
}
if (power1 > temporary->power && power1 < temporary->Next->power) {
node->Next = temporary->Next;
temporary->Next = node;
return;
}
temporary = temporary->Next;
}
//insert at last
if (temporary->power == power1) {
temporary->coefficient = temporary->coefficient + coefficient1;
return;
}
temporary->Next = node;
Tail = node;
}
void Polynomial::remove(int pw)
{
if (Head == NULL)
return;
//only one node
if (Head->power == pw && Head == Tail) {
delete Head;
Head = Tail = NULL;
return;
}
Node* temporary = Head;
while (temporary->Next != NULL) {
if (pw == temporary->Next->power)
{
Node* node = temporary->Next;
temporary->Next = temporary->Next->Next;
if (temporary->Next == NULL)
Tail = temporary;
delete node;
return;
}
temporary = temporary->Next;
}
}
double Polynomial::Evaluate(double value)
{
Node* temporary = Head;
double result = 0.0;
while (temporary != NULL) {
result =result+ (temporary->coefficient * pow(value, temporary->power));
temporary = temporary->Next;
}
return result;
}
/*Polynomial& Polynomial::operator=(Polynomial& p)
{
Node* temporary = p.Head;
int pp;
int cc;
removeAll();
while (temporary != nullptr) {
pp = temporary->getpower();
cc = temporary->getcoefficient();
insert(cc,pp);
temporary = temporary->Next;
}
return *this;
}*/
int Polynomial::degree() const
{
if (Head == NULL)
{
cout << "Empty polynomial\n";
return -1;
}
return Tail->power;
}
void Polynomial::merge(Polynomial p)
{
int count = 0;
Node* temporary = p.Head;
while (temporary != NULL) {
insert(temporary->coefficient, temporary->power);
temporary = temporary->Next;
}
p.removeAll();
return;
}
void Polynomial::removeAll()
{
if (Head == NULL)
return;
Node* CurrentNode = Head;
Node* NextNode = NULL;
while (CurrentNode != NULL)
{
NextNode = CurrentNode->Next;
delete CurrentNode;
CurrentNode = NextNode;
}
Head = Tail = NULL;
}
istream& operator>>(istream& in, Polynomial& P)
{
int num;
cout << "Please enter number of nodes\n";
cin >> num;
int c, p;
for (int i = 0; i < num; i++)
{
cout << "Please enter the pair of (coefficient,power)\n";
in >> c >> p;
P.insert(c, p);
}
return in;
}
ostream& operator<<(ostream& out, const Polynomial& P)
{
Node* temporary = P.Head;
if (temporary == NULL)
{
out << "Empty polynomial\n";
return out;
}
else {
out << "Polynomial is:\n";
while (temporary != NULL) {
if (temporary->power == 0)
out << temporary->coefficient << " + ";
else if (temporary->Next == NULL)
out << temporary->coefficient << "x^" << temporary->power;
else
out << temporary->coefficient << "x^" << temporary->power << " + ";
temporary = temporary->Next;
}
}
out << endl;
return out;
}
//Polynomial operator+(Polynomial& p1, Polynomial& p2)
Polynomial Polynomial::operator+(Polynomial O2)
{
Polynomial SumOfPolies;
Node* temporary = Head;
while (temporary != NULL) {
SumOfPolies.insert(temporary->coefficient, temporary->power);
temporary = temporary->Next;
}
temporary = O2.Head;
while (temporary != NULL) {
SumOfPolies.insert(temporary->coefficient, temporary->power);
temporary = temporary->Next;
}
return SumOfPolies;
}
and this is the main
#include <iostream>
#include "Polynomial.h"
using namespace std;
int main()
{
int X[] = { 2,4,1,3,5 };
int Z[] = { 1,2,0,3,4 };
Polynomial F1(X, Z, 5);
cout << F1 << endl;
cout << F1.degree() << endl;
Polynomial F2;
F2.insert(3, 2);
F2.insert(1, 6);
F2.insert(2, 7);
cout << F2 << endl;
Polynomial F3;
cout << "Here\n";
F3 = F1 + F2;
cout << "Here\n";
cout << F3;
return 0;
}
IMHO it's the time you should learn using debugger.
But if I had to guess I would say the most suspicious part I see in your code so far is this instruction:
return SumOfPolies;
in Polynomial Polynomial::operator+(Polynomial O2).
With this return you cause the program to make a copy of a local variable SumOfPolies. However, you did not provide a copy constructor to the Polynomial class, so compiler creates a default copy member-by-member. This means a copied object, which shall be returned, shares the same list of Nodes with SumOfPolies. But SumOfPolies will be destroyed immediately after, because this is just return from the method – and in the destructor if will delete all its Nodes thus invalidating the Head and Tail pointers in the returned copy.
There are other mistakes and imperfections, unrelated to what you experience now.
For example, you create a new Node object in the insert method even though if may be unnecessary if power1 == Head->power – but you do not delete it, and the abandoned Node object remains in memory for ever (or rather until your program terminates).
You mix NULL and nullptr.
You also declared some variables where they're not necessary. For example in removeAll() the NextNode is not necessary at the function's scope, it may well be defined within the loop. You can drop the CurrentNode as well:
void Polynomial::removeAll()
{
while (Head != NULL)
{
Node* NextNode = Head->Next;
delete Head;
Head = NextNode;
}
Tail = NULL;
}
You may also drop using the Tail member. As far as I can see you need to initialize or modify it in seven places of your program, but you use it just in two—and you can easily get rid of it in both of them!
One is in remove(int pw) where you compare Tail to Head to check if the list is a single node only. Note this can be accomplished just by testing if Head->Next == NULL.
The other one is in degree(), where you need to access the highest power node. But you could test the Head node instead if only you reverse the order in which powers are stored.
With this simple change you would simplify nine pieces of your code! I suppose this is worth inverting direction of one < and two > operators.
You need a copy constructor that looks like this:
Polynomial::Polynomial(Polynomial const& other)
{
Node* head = other.Head;
while (head != nullptr)
{
insert(head->coefficient, head->power);
head = head->Next;
}
}
When you provide a user-defined implementation of it, you should also implement the copy assignment operator, the move constructor and the move assignment operator. See the Rule of Five and the Rule of Zero: https://en.cppreference.com/w/cpp/language/rule_of_three.
so I was trying to build this project on deque using the doubly linked list. but when I build it. it says build but gives threads and doesn't give the output as required.
I have re-implemented the major problem(copy constructor) and all the functions again and again but then it still gives me new threads every time.
this is the header file.
#pragma once
#include <stdexcept>
using namespace std;
class Node
{
public:
int data;
Node* next;
Node* previous;
Node();
Node(const int &x);
};
class Deque
{
public:
Deque();
Deque(const Deque &d);
Deque &operator= (const Deque &d);
~Deque();
void insertFront(const int &x);
void insertBack(const int &x);
int removeFront();
int removeBack();
int peekFront();
int peekBack();
bool empty() const;
int size()const;
friend ostream& operator << (ostream &out, const Deque &d);
private:
Node* front;
Node* rear;
};
this will be the .cpp (implementation file.)
//
// Deque_cmpt225.cpp
// Deque_cmpt225
//
// Created by Aryan Arora on 2017-10-09.
// Copyright © 2017 Aryan Arora. All rights reserved.
//
#include "Deque_cmpt225.h"
#include <iostream>
#include <stdexcept>
using namespace std;
Node:: Node()
{
previous = nullptr;
next = nullptr;
data = 0;
}
Node:: Node(const int &x)
{
Node();
data = x;
}
Deque:: Deque() //Empty Deque.
{
front = nullptr;
rear = nullptr;
}
Deque:: ~Deque()
{
if (this->empty())
return;
else{
Node* temp;
while (this->front->next != nullptr){
temp = this->front;
this->front = this->front->next;
delete temp;
}
temp = this->front;
this->front = nullptr;
this->rear = nullptr;
delete temp;
}
}
Deque:: Deque (const Deque &d) //Copy Constructor
{
if (d.empty()) //Deque is empty.
{
return;
}
Node* temp = d.front;
int x;
if (temp->next == nullptr) //Deque of just one node
{
x = temp->data;
Node *n1 = new Node (x);
n1->next = nullptr;
n1->previous = nullptr;
this->front = n1;
this->rear = n1;
}
else //Deque has more than one node
{
while (temp!= nullptr)
{
this->insertBack(temp->data);
temp = temp -> next;
}
}
}
Deque& Deque:: operator=(const Deque &d) //============================check again
{
if (this == &d)
return *this;
else
{
this->~Deque(); //DELETING THE DEQUE
Node* temp = d.front; //COPYING EACH NODE
while (temp != NULL)
{
this->insertBack(temp->data); //INSERTING AT THE BACK
temp = temp->next; //POINTING TEMP TO NEXT NODE
}
}
return *this;
}
void Deque:: insertFront(const int &x)
{
Node* temp = new Node(x);
temp->next = nullptr;
temp->previous = nullptr;
if (empty())
{
this->front = temp;
this->rear = temp;
}
else
{
temp->next = this->front;
temp->previous = nullptr;
this->front->previous = temp;
this->front = temp;
}
}
void Deque:: insertBack(const int &x)
{
Node* temp = new Node(x);
temp->next = nullptr;
temp->previous = nullptr;
if (empty())
{
this->front = temp;
this->rear = temp;
}
else
{
temp->next = nullptr;
temp->previous = this->rear;
this->rear->next = temp;
this->rear = temp;
}
}
int Deque:: removeFront()
{
if (empty()) //=================runtime error
{
throw std::runtime_error("The que is empty.");
}
else{
Node* temp;
temp = this->front;
int x = temp->data;
if ( this->front->next != nullptr )
{
this->front = this->front->next;
this->front->previous = nullptr;
}
else
{
this->front = nullptr;
this->rear = nullptr;
}
delete temp;
return x;
}
}
int Deque:: removeBack()
{
if (empty()) //=================runtime error
{
throw std::runtime_error("The que is empty.");
}
else{
Node* temp = this->rear;
int x = temp->data;
if ( this->rear->previous != nullptr )
{
this->rear = this->rear->previous;
this->rear->next = nullptr;
}
else
{
this->rear = nullptr;
this->front = nullptr;
}
delete temp;
return x;
}
}
int Deque:: peekFront()
{
if (empty()) //=================runtime error
{
throw std::runtime_error("The que is empty.");
}
else
{
return this->front->data;
}
}
int Deque:: peekBack()
{
if (empty()) //=================runtime error
{
throw std::runtime_error("The que is empty.");
}
else
{
return this->rear->data;
}
}
bool Deque:: empty() const
{
if (this->front == nullptr && this->rear == nullptr)
return true;
else
return false;
}
int Deque:: size() const
{
Node* temp = this->front;
int count = 0;
while (temp != nullptr)
{
count++;
temp = temp->next;
}
return count;
}
ostream& operator << (ostream &out, const Deque &d)
{
Node* temp = d.front;
out << "NULL -> ";
while (temp != nullptr)
{
out << temp->data << " <-> ";
temp= temp->next;
}
out << "<- NULL" << endl;
return out;
}
thanks in advance.
Your code has many problems..
Your Node constructor doesn't delegate properly..
Node::Node()
{
previous = nullptr;
next = nullptr;
data = 0;
}
Node::Node(const int &x)
{
Node(); //Creates a temporary node that gets destroyed immediately..
data = x;
}
It's much simpler if you change it to:
Node::Node() : Node(0) //Delegating constructor.
{
}
Node::Node(const int &x) : previous(nullptr), next(nullptr), data(x)
{
}
This point isn't really a problem, but worth mentioning.. You keep setting the Node pointers to nullptr right after construction. This is not necessary because your constructor already does that..
Node* temp = new Node(x);
temp->next = nullptr; //Not needed anymore with the above fixes.
temp->previous = nullptr; //Not needed anymore with the above fixes.
You never initialize your variables in the copy constructor..
In your constructor, you have (I changed it, but it has the same meaning):
Deque::Deque() : front(nullptr), rear(nullptr)
{
}
But in your copy constructor, you have:
Deque::Deque(const Deque &d)
{
//Other code here.. You never initialized front and rear to nullptr..
}
You never set front and rear to nullptr so empty() returns false since they are a "random" uninitialized value.. Then in insertBack you go on to access this and boom.. Access Violation.
To fix it, you do:
Deque::Deque(const Deque &d) : front(nullptr), rear(nullptr)
{
//Other code here..
}
Next issue is that your copy assignment operator is calling the destructor!
Deque& Deque::operator=(const Deque &d)
{
if (this == &d)
return *this;
else
{
this->~Deque() //YOU CANNOT DO THIS.. Create a private member function for cleaning up.. Then call that function in your destructor and call that function here.. You cannot invoke the destructor like this.
}
//....
}
I tried using cout at various stages to figure but in vain. The program crashes after flushing the first two values in the reversed list. It prints a garbage value as the third value and before it can print the last two values, it crashes.
#include <iostream>
using namespace std;
class LLStack {
public:
struct Node {
int data;
Node* next;
Node(int n) {
data = n;
next = 0;
}
Node(int n, Node* node) {
data = n;
next = node;
}
};
LLStack();
LLStack(const LLStack&);
LLStack& operator = (const LLStack&);
~LLStack();
void push(int);
int pop();
int top();
bool isEmpty();
void flush();
private:
Node* head;
};
LLStack::LLStack() {
head = 0;
}
LLStack::LLStack(const LLStack& s) {
head = new Node(NULL);
head->data = s.head->data;
if (s.head->next != NULL) {
head->next = new Node(*(s.head->next));
}
else {
head->next = new Node(NULL);
}
}
LLStack::~LLStack() {
this->flush();
}
LLStack& LLStack::operator = (const LLStack& s) {
this->head = new Node(NULL);
this->head->data = s.head->data;
if (s.head->next != NULL) {
this->head->next = new Node(*(s.head->next));
}
else {
this->head->next = new Node(NULL);
}
return *this;
}
void LLStack::push(int x) {
if (head == 0) head = new Node(x);
else {
Node* temp = new Node(x, head);
head = temp;
}
}
int LLStack::pop() {
if (head == 0) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
else {
Node* temp = head;
int n = temp->data;
head = temp->next;
delete temp;
return n;
}
}
int LLStack::top() {
if (head == 0) {
cout << "\n\nNo elements in the stack\n\n";
return -1;
}
else {
return head->data;
}
}
bool LLStack::isEmpty() {
return (head == 0);
}
void LLStack::flush() {
if (head == 0) {
cout << "\n\nNo elements in the Stack to flush\n\n";
return;
}
cout << "\n\nFlushing the Stack: ";
Node* temp = 0;
while (head != 0) {
temp = head;
cout << temp->data << " ";
head = head->next;
delete temp;
}
cout << endl << endl;
}
void reverseStack(LLStack& s1) {
LLStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
}
int main() {
LLStack s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
reverseStack(s);
cout << "\n\nFlushing s:\n";
s.flush();
return 0;
}
I tried using cout at various stages to figure but in vain. The program crashes after flushing the first two values in the reversed list. It prints a garbage value as the third value and before it can print the last two values, it crashes.
#include <iostream>
using namespace std;
class LLStack {
public:
struct Node {
int data;
Node* next;
Node(int n) {
data = n;
next = 0;
}
Node(int n, Node* node) {
data = n;
next = node;
}
};
LLStack();
LLStack(const LLStack&);
LLStack& operator = (const LLStack&);
~LLStack();
void push(int);
int pop();
int top();
bool isEmpty();
void flush();
private:
Node* head;
};
LLStack::LLStack() {
head = 0;
}
LLStack::LLStack(const LLStack& s) {
head = new Node(NULL);
head->data = s.head->data;
if (s.head->next != NULL) {
head->next = new Node(*(s.head->next));
}
else {
head->next = new Node(NULL);
}
}
LLStack::~LLStack() {
this->flush();
}
LLStack& LLStack::operator = (const LLStack& s) {
this->head = new Node(NULL);
this->head->data = s.head->data;
if (s.head->next != NULL) {
this->head->next = new Node(*(s.head->next));
}
else {
this->head->next = new Node(NULL);
}
return *this;
}
void LLStack::push(int x) {
if (head == 0) head = new Node(x);
else {
Node* temp = new Node(x, head);
head = temp;
}
}
int LLStack::pop() {
if (head == 0) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
else {
Node* temp = head;
int n = temp->data;
head = temp->next;
delete temp;
return n;
}
}
int LLStack::top() {
if (head == 0) {
cout << "\n\nNo elements in the stack\n\n";
return -1;
}
else {
return head->data;
}
}
bool LLStack::isEmpty() {
return (head == 0);
}
void LLStack::flush() {
if (head == 0) {
cout << "\n\nNo elements in the Stack to flush\n\n";
return;
}
cout << "\n\nFlushing the Stack: ";
Node* temp = 0;
while (head != 0) {
temp = head;
cout << temp->data << " ";
head = head->next;
delete temp;
}
cout << endl << endl;
}
void reverseStack(LLStack& s1) {
LLStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
}
int main() {
LLStack s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
reverseStack(s);
cout << "\n\nFlushing s:\n";
s.flush();
return 0;
}
Please run it and you'll understand for yourself.
The problem is in function:
void reverseStack(LLStack& s1) {
LLStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
}
Here you are creating the local stack "s2". When the s2 goes out of scope, it calls the destructor and flushes the whole stack. Better you should remove the flush call from destructor or create the global "s2". Best option will be implement the other logic to reverse the stack.
To start, the max size of this list is 30 and the number of items in each list created is stored in num_items, which is incremented and decremented by push and pop methods i have elsewhere but i am wondering if i need to keep track of the num_items here as well. I will show the output i'm expecting along with the output i am getting:
I will now show the code that copies my stack:
void operator=(const Stack& s)
{
if (s.top == NULL)
top = NULL;
else
{
top = new Node;
top->data = s.top->data;
Node* newP = top;
for(Node* curr = s.top->link; curr != NULL; curr = curr->link)
{
if(num_items != MAX_SIZE)
{
newP->link = new Node;
newP = newP->link;
newP->data = curr->data;
}
}
}
}
The code that is supplying the output is:
Stack<int> s2(s1); // s2 declared as a copy of s1
cout << "*declare s2 as a copy of s1 (stack s2(s1))\ns2=" << s2 << endl;
cout << "s2.Size()=" << s2.Size() << endl;
cout << "s2.IsEmpty()=" << ((s2.IsEmpty()) ? "T" : "F") << endl;
cout << "s2.IsFull()=" << ((s2.IsFull()) ? "T" : "F") << endl;
cout << "s2.Peek()=" << s2.Peek() << endl;
cout << endl;
Edit:
After initializing num_items = 0; in the code i will show below
void operator=(const Stack& s)
{
if (s.top == NULL)
top = NULL;
else
{
top = new Node;
top->data = s.top->data;
Node* newP = top;
for(Node* curr = s.top->link; curr != NULL; curr = curr->link)
{
num_items = 0;
if(num_items != MAX_SIZE)
{
newP->link = new Node;
newP = newP->link;
newP->data = curr->data;
num_items++;
}
}
}
}
The output i get for my size turns out to be 1, i will show the whole output again in an image:
Second Edit:
I have now modified my code to the following:
void operator=(const Stack& s)
{
if (s.top == NULL)
top = NULL;
else
{
top = new Node;
top->data = s.top->data;
Node* newP = top;
num_items = 0;
for(Node* curr = s.top->link; curr = NULL; curr = curr->link)
{
if(num_items != MAX_SIZE)
cout<< num_items;
{
newP->link = new Node;
newP = newP->link;
newP->data = curr->data;
++num_items;
}
}
}
}
with this though i my size only counts up to 9 instead of 10, i figure because my loop is skipping over 0 or "NULL" rather, but there must be a way to make it stop doing that.
A single list is best copied while maintaining a Node** store pointing to the variable that needs to be set to the next Node*:
void operator=( const Stack& rhs ){ // or return Stack&
// call this->clear() to avoid memory leak
if( rhs.top == NULL ){ top = NULL; return /* *this */; }
Node** store = ⊤
for( Node* curr = rhs.top; curr != NULL; curr = curr->link ){
Node* newNode = new Node;
num_items++;
newNode->data = curr->data;
*store = newNode;
store = &newNode->link;
}
return /* *this */;
}
This assignment operator will produce a memory leak unless care is taken to remove any existing entries. Perhaps there's already a clear() method?
Later:
These constructors might be used:
Stack() : num_items(0), top(NULL) {}
Stack( const Stack& other ) {
*this = other;
}
This clear method should be used where indicated:
void clear(){
Node* curr = top;
while( curr != NULL ){
Node* next = curr->link;
delete curr;
curr = next;
}
}
Stack<int> s2(s1);
This calls the default copy constructor and not the operator=. However, since your copy logic is implemented in the operator=, the nodes are never copied into s2.
You need to write a copy constructor and move the logic from operator= into it:
Stack(const Stack & other)
{
// Copy other stack here
}