So I am trying to implement a Stack using a linked list and classes. Right now I have 6 different files: node.h, node.cpp, LL.h, LL.cpp, Stack.h, and Stack.cpp. I want to complete the Stack.h and Stack.cpp files so that they work as they should. I already implemented the linked list functions and they work as they should. Here is the code:
node.h :
// node.h
class node { // node class used in the LL (linked list) class
private:
node * next; // Pointer to next node of an LL
int data; // integer data stored in this node
public:
node(int x, node * n); // Constructor
~node(); // Destructor
void set_data(int x); // Change the data of this node
void set_next(node * n);// Change the next pointer of this node
int get_data(); // Access the data of this node
node * get_next(); // Access the next pointer of this node
};
LL.h :
// LL.h
#include "node.h"
// Linked list class, used in the Stack class
class LL {
private:
node * head; // pointer to first node
node * tail; // pointer to last node
public:
LL(); // Constructor
~LL(); // Destructor
void prepend(int value); // add a node to the beginning of the LL
int removeHead(); // remove the first node of the LL
void print(); // print the elements of the LL
node * get_head(); // access the pointer to the first node of the LL
};
Stack.h:
// Stack.h
#include "LL.h"
class Stack {
private:
LL_t intlist;
public:
Stack(); // Constructor
~Stack(); // Destructor
void push(int value);
int pop();
int isEmpty();
void print();
};
And lastly,
Stack.cpp:
// Stack.cpp
#include "Stack.h"
#include <stdio.h>
Stack::Stack() {
head= NULL;
tail= NULL;
}
Stack::~Stack() {
delete intlist;
}
int Stack::isEmpty() {
return (head==NULL);
}
void Stack::push(int value) {
head= value;
}
int Stack::pop() {
if ( !isEmpty() ) {
int temp= tail->get_data();
delete tail;
return temp;
}
return -1;
}
I am having compiling issues. It says get_data() is undefined and "head" and "tail" is undefined, even though I have " #include "LL.h" " in Stack.h and in LL.h, I have "#include "node.h" ", so they all build on one another so it should work correct? I want it to compile so I can see if I am implementing Stack.h and Stack.cpp correctly. Do you see any issues with the way I am implementing them? If so, can you point them out? Also, any idea as to why I am getting these compiling issues? Any help appreciated!
Let's look at your actual questions
Stack::Stack() {
head= NULL;
tail= NULL;
}
results in error "head" and "tail" is undefined. Now look at the header files, where are the declarations of head and tail? Answer, in the LL class not the Stack class. It's the responsibility of the LL class to initialise head and tail which it does the in the LL class default constructor. So your Stack constructor should look like this
Stack::Stack() {
}
Whenever you have a constructor for a class which contains another class a constructor for the other class will be called. In the case of Stack the default constuctor for LL is called implicitly, and this initialises head and tail for you. You don't have to do anything.
Now lets look at some more of your implementation.
Stack::~Stack() {
delete intlist;
}
intList is not a pointer, so it cannot be deleted. It's clear that you are trying to 'call` the destructor for your list, but just like the constructor this happens automatically. Your destructor should look like this
Stack::~Stack() {
}
Or you could (probably should) just remove it completely.
Moving on
int Stack::isEmpty() {
return (head==NULL);
}
Again you are trying to access head somewhere it isn't accessible. Your Stack class has an LL intlist object and that's what it should use, so (for instance)
int Stack::isEmpty() {
return intlist.get_head() == NULL;
}
Smae thing here
void Stack::push(int value) {
head= value;
}
should be
void Stack::push(int value) {
intlist.prepend(value);
}
Use the object that the stack has (the intlist) not the internals of other objects.
I'll leave you do sort out the rest. But you must understand the division of responsbilities that exist in your class design. The Stack class should not (and cannot) concern itself with the internals of the LL class. All that the operations that Stack needs to perform should be doable with the public interface of the LL class. If not then it's the LL class that needs to change.
Also note that your pop implementation is not just wrong in executuion it's wrong in concept. Pop should remove the head of the list, not the tail. A stack is a LIFO list (last in, first out) so pop removes the most recentaly added item. Now looking at the LL class there is a removeHead method (hint, hint).
Related
I want to implement single linked list with a header class but i am also trying making information and pointer of linked list private and compiler says me
lvalue required as left operand of assignment
pred->Next()=temp->Next();
What's the wrong with this code?
#include <iostream>
using namespace std;
class IntSLLNode{
private:
int info;
IntSLLNode * next;
public:
IntSLLNode(){
next=0;
}
IntSLLNode(int el,IntSLLNode *ptr=0){
info=el;
next=ptr;
}
int Info(){return info;}
IntSLLNode * Next(){return next;}
};
IntSLLNode * head,* tail;//header structure
class IntSLList{
IntSLList(){
head=0; tail=0;
}
public:
void addToHead(const int&);
void addToTail(const int &);
int deleteFromHead();
int deleteFromTail();
void deleteNode(int&);
void listele();
};
void IntSLList::addToHead(const int &el){
head=new IntSLLNode(el,head);
if(tail==0)
tail=head;
}
void IntSLList::addToTail(const int &el){
if(tail==0){
head=tail=new IntSLLNode(el,head);
}
else{
tail->Next()=new IntSLLNode(el);
tail=tail->Next();
}
}
int IntSLList::deleteFromHead(){
if(head==0){
cout<<"No value such that";
return -1;
}
int el=head->Info();
IntSLLNode * temp=head;
if(head==tail){
head=tail=0;
}
else{
head=head->Next();
}
delete temp;
return el;
}
First of all, you need to understand the difference between lvalue and rvalue. In simple words, lvalue is something that can be assigned (variable etc.) while rvalue is a temporary value (just like the one that you are returning here: IntSLLNode * Next(){return next;})
Then, by trying to assign something to rvalue, you get an error.
As a solution here, you could make your IntSLLNode * next; public or return a reference to this class member in your Next() function.
Assignment to a return value of a function/method would not do anything useful. You can only assign to a reference of a value returned by a function.
class IntSLLNode{
...
int& Info(){return info;}
IntSLLNode*& Next(){return next;}
};
But then, it would break encapsulation of that node and would allow any external code to change the linking of your nodes in the list by mistake. Personally I would hide the whole node class into the list class and provide methods to access Info() values to code outside this file.
I have made a superclass named "tree". I have constructed the tree in this class. Now, I want to pass the root of the constructed tree to another class which is a subclass of tree. But when I try to pass it, the subclass calls the supercalss constructor and sets it to NULL;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
This is the definition of my tree class. It just creates a tree with one node having value 5. Now I want to pass the new root created to a subclass of tree.
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
I create an object for tree first and then do createtree. Now, when I create an object for treeiterator, it's member p gets sets to NULL since supercalss constructor is also called. How can I just access the tree created in the superclass in subclass?
Full code:
#include <bits/stdc++.h>
using namespace std;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
void treeiterator::push(struct node *t)
{
while(t) {
s.push(t);
t = t->left;
}
}
bool treeiterator::hasnext()
{
return s.empty()?1:0;
}
int treeiterator::next()
{
struct node *t = s.top();
int val = t->val;
s.pop();
if(t->right) {
push(t->right);
}
return val;
}
int main()
{
tree t;
t.createtree();
t.preorder();
treeiterator it;
while(it.hasnext()) {
cout<<it.next()<<' ';
}
}
Because of inheritance every treeiterator is also a tree. This means
treeiterator treeIt;
treeIt.createtree();
will do what OP wants. There is no need to make a separate tree and moving the root around.
However this is a bit odd in the world of C++ because OP is under-using the constructor. For example, node could be:
struct node
{
node *left;
node *right;
int val;
node(int inval):
val(inval),
left(nullptr),
right(nullptr)
// the above is a Member Initializer List. It makes sure all of your
// members are initialized before the body of the constructor runs.
{
}
};
That bit after the : in the constructor is the Member Initializer List.
Now when you allocate a node it's initialized and ready to be linked. For tree
class tree
{
public:
struct node *root; // almost certainly should not be public.
// also should be a std::unique_ptr<node>
tree(int inval)
{
root = new node(5); // note new in place of malloc. new allocates
// storage and calls constructors. malloc should
// only be used in C++ in rare edge-cases.
}
/* obsolete
void createtree()
{
root = create(5);
}
*/
...
};
tree is assigned a root on allocation. treeiterator is a wee bit trickier because it must call tree's constructor to set up root.
class treeiterator:public tree
{
struct node *p; // Don't see the point off this
stack<struct node *> s; // or this, but that's another question
public:
treeiterator(int inval):
tree(inval) // call's tree's constructor
{
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
Allocating a treeiterator now guarantees that it is all ready to go with no further work.
treeiterator treeIt(5); // all done.
All of the above is covered within the first few chapters of any good C++ programming text. I recommend getting one and reading it, because right now it looks like you are trying to write bad C.
Off topic 1:
You are going to quickly find that this code is in violation of the Rule Of Three. What is The Rule of Three? If you don't know, read the link. It will save you much time and hair-pulling
Off Topic 2:
#include <bits/stdc++.h>
using namespace std;
Is a ticking time bomb. The first line includes the entire standard library, but only in GCC. Your code is now doing far, far more work than it need to to compile, is no longer standard C++, and is not portable to other compilers and may well break with the next revision of GCC. Don't use anything in bits. It internal compiler-specific stuff with no guarantees what-so-ever.
More here: Why should I not #include <bits/stdc++.h>?
The second line takes everything in the std namespace and places it in the global namespace. This leads to fun games like is reverse or std::reverse being called? Often this leads to insane and arcane compiler messages because the poor compiler is confused as hell, but sometimes it's not confused and picks the best choice among the many and silently breaks something else. Great fun debugging.
More here: Why is "using namespace std" considered bad practice?
Together you have the entire standard library pulled into your file AND stripped of it's proper namespace. This results in a vast minefield of potential hidden pain that is not worth any perceived time savings. One of the resulting bugs could cost more clean up than years of typing a few extra lines per file and characters.
No one want to clean up code with this stupid a mistake, so doing this in a professional setting can be costly.
First, you should not have root has public. This is a gross OO error. If you want it to be available to subclasses you should make it protected.
I've successfully implemented a recursive PrintList method, so I don't understand why a recursive destructor won't work:
//recursively deleting nodes in a doubly linked list
LinkedList::~LinkedList()
{
if (Head == 0) //base case
{
Tail = 0; //fixing the dangling Tail pointer doesn't seem to fix the error...
return;
}
else
{
Node* temp = Head;
Head = Head->getNext();
cout << "deleting " << temp->getNumber() << endl;
delete temp;
delete this;
}
}
When debugging, I get the _Block_Type_Is_Valid (pHead->nBlockUse) Error after calling the LinkedList destructor, just before the program could finish up "nicely". This is past "return 0;" in main.cpp, and I stepped through the destructor code shown above with no problem, and indeed the destructor gave me all the correct test messages and worked as intended.
Even more frustrating was that I can't locate what caused this error: I tried to "step over" beyond the LinkedList destructor code, but I got the message from VS: "Source Not Available: Source information is missing from the debug information for this module". I was thinking the dangling Tail pointer (which points at a random memory after the destructor executes) might be a problem, so I set "Tail=0;" before returning from the base case, but that doesn't seem to be working.
The only way I can suppress this error is by either:
constructing a LinkedList then simply ending the program without adding any nodes into it (no problem deleting an empty LinkedList), or
making my LinkedList in main dynamically allocated, and ending the program without manually deleting it (skipping the entire LinkedList destructor)
What is the problem here? Help!!
UPDATE: My fantastic CS professor pointed out my problem:
"When the destructor exits and attempts the automatic deallocation of the node, it has already been destroyed by the delete this statement.
When the delete keyword is used, it initiates the destructor and then deallocates the memory."
So like #0x499602D2 pointed out, "delete this" was the problematic line, but it had nothing to do with whether my LinkedList was NEWed and then deleted or statically created at compile time then automatically destroyed. Essentially it was caused by the behavior of the destructor.
The solution therefore is: changing "delete this;" to "this->~LinkedList();"
Only by "this->~LinkedList();" can I make recursive calls to the destructor without really "deleting" the calling object; instead it'll be destroyed when the destructor exits and does the automatic deallocation, avoiding the mistake of deleting it again.
More details:
Here's my implementation of Node (doubly linked). It derives from a singly-linked BaseNode class:
//Specification file for BaseNode class
#ifndef BASENODE_H
#define BASENODE_H
#include <iostream>
class BaseNode
{
protected:
char * name;
int number;
BaseNode * next;
public:
//default constructor
BaseNode();
//overloaded constructor
BaseNode(const char *, int);
//destructor
~BaseNode() {
std::cout << "name is: " << name << '\n';
delete[] name;
}
//getter functions
char * getName() const { return name; }
int getNumber() const { return number; }
BaseNode* getNext() { return next; }
//setter functions
void setNumber(int num){ number = num; };
void setNext(BaseNode* ptr) { next = ptr; }
};
#endif
//Implementation file for BaseNode class
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <cstring>
#include "BaseNode.h"
//default constructor
BaseNode::BaseNode()
{
name = 0;
number = 0;
next = 0;
}
//overloaded constructor
BaseNode::BaseNode(const char * str, int num)
{
roman = new char[strlen(str) + 1]; //set aside one more character for null terminator
strcpy(name, str);
number = num;
}
Then my Node class inherits the BaseNode class:
#ifndef Node_H
#define Node_H
#include "BaseNode.h" //include the base class for inheritance to work
class Node : public BaseNode
{
protected:
Node * prev;
Node * next;
public:
Node() : BaseNode()
{ prev = next = 0; }
Node(const char * namestr, int num) : BaseNode(namestr, num)
{ prev = next = 0; }
//empty destructor; the BaseNode destructor automatically gets called from here and does the job
~Node() { }
//getter functions and setter functions are all inherited from BaseNode, except that....
//the BaseNode version of getNext and setNext won't work for our Node class
Node* getNext() const { return next; }
void setnext(Node* pointer) { next = pointer; }
Node* getPrev() const { return prev; }
void setPrev(Node* pointer) { prev = pointer; }
};
#endif
I've created class for building a linked list. The class declaration is as follows:
class LinkedList
{
private:
int data;
LinkedList *next;
static int count;
public:
LinkedList(void);
~LinkedList(void);
int insert(int arg);
int remove(int arg);
bool find(int arg);
};
How can I make sure all nodes of this linked list are deleted? The destructor is made responsible for deleting just one node. I used to make linked list like this previously but never thought about clearing the memory.
The naive implementation
~LinkedList() {delete next;}
will do the right thing - delete will call the destructor on the next element, which will delete the one following it, and so on, to delete the whole list.
However, this means that the destructors are called recursively, so that deleting a very long list could cause a stack overflow. Iteration might be better:
~LinkedList() {
while (LinkedList * head = next) {
next = head->next;
head->next = nullptr;
delete head;
}
}
As noted in the comments, it might be more appropriate to have separate List and Node classes, with List responsible for memory management, and Node a simple aggregate containing the data and the link. Then there's less scope for error in the destructor, as it doesn't need to nullify any pointers to prevent recursion:
struct Node {
int data;
Node * next;
};
struct List {
Node * head;
~List() {
while (Node * victim = head) {
head = victim->next;
delete victim;
}
}
};
I spent a lot of time to understand the problem.I don't know why it occurred.Maybe you guys can find out and understand the problem.I wrote the necessary comments.Here is my code:
#include <iostream>
struct node{
////I am creating node structure.
int number;
node *next;
node *previous;
};
struct list{
////I am creating list structure.It has head and tail pointers
node *head;
node *tail;
void add(node *); // Add function
void create(); // Create function
void deleteList(); // Delete function.
}emrah;
using namespace std;
int main(){
emrah.create(); // a list called 'emrah' has been created.
cout<<"Type 1."<<endl; // So that we lead user to add a node.
int selection;
cin>>selection;
if (selection==1){ // Suppose user typed 1.
node x;// new node is x.
emrah.add(&x); // x has been sent.
cout<<x.number; // Problem is here.On the command line,it shows like -9231
}
}
void list::create(){ // Create function.It has no problem.
head=NULL;
tail=NULL;
}
void list::add(node *Node){ // I think problem is around this function.
Node=new node;
cout<<"Sayi gir"<<endl;
cin>>Node->number;
cout<<Node->number;
head=tail=Node;
}
I am getting x's value that is different than I type on the command line.Where is the point that I miss?
Thanks.
In add, you overwrite the argument Node with a new object that receives the user input. x is never touched within list::add.