i need to show all elements of a stack and queue, using static structures i used a recursive function, but with dynamic it doesnt works well at all.
When i use the functions, it shows the elements correctly, but after that, whatever i do, the program crashes.
Also, in order to do the print(), a requeriment is that it suppose that i can only have acces to the top, so if i show the top, i cant see the previous node, unless i pop the current top, then show the new top.
This is the code for the dynamic stack:
class Person{
public:
string nombre,weight;
Person *sig;
public:
void Capture();
void Show();
};
typedef Person *pPerson;
class stack{
public:
pPerson top;
void Push();
void PushPtr(pPerson object);
void Pop();
pPerson Top();
void Print();
};
//Push new elements
void stack::Push(){
pPerson newP;
newP=new Person();
newP->Capture();
if(top==NULL){
newP->next=NULL;
top=newP;
}
else{
newP->next=top;
top=newP;
}
size++;
}
//For print
void Stack::Print(){
if(Empty()){
return;
}
pPerson x=Top();
Pop();
Print();
PushPtr(x);
}
//Function to recieve the "x" pointer
void Stack::PushPtr(pPerson object){
pPerson newP;
newP=object;
if(size==0){
newP->next=NULL;
top=newP;
}
else{
newP->next=top;
top=newP;
}
size++;
}
As i said, the queue is doing the same thing, but figuring out whats the problem here, im pretty sure i'll fix the queue :-/
Thanks in advance.
Stack walks are usually done this way:
void Stack::Print(){
pPerson cur = top;
while (cur != nullptr) {
cur->printIt(); // other print function.
cur = cur->next;
}
}
Unless there is some existential reason to pop the stack and push it back on.
Related
I wanted to know how to make sure I'm not leaking memory when calling delete on a singly-linked list (implemented by hand, btw).
I created these super basic list,node and person classes to make myself a little bit clearer.
Here you go:
class person {
public:
person();
//something to do like sets gets etc...
virtual ~person();
private:
int id;
person* pplArr[5]; //Dynamically allocated person objs.
};
person::person(){
pplArr[5] = NULL;
}
person::~person(){
for(int i = 0; i < 5; i++)
delete pplArr[i];
}
#include "person.h"
class node {
public:
node(person*, node*);
person* getData();
node* getNext();
void setNext(node*);
virtual ~node();
private:
person* data;
node* next;
};
node::node(person* p, node* n){
data = p;
next = n;
}
person* node::getData(){
return data;
}
node* node::getNext(){
return next;
}
void node::setNext(node* nxt){
next = nxt;
}
node::~node(){
//nothing to delete "manually".
}
#include "node.h"
class list {
public:
list();
node* getFirst();
void insert(person*);
virtual ~list();
private:
node* first;
};
node* list::getFirst(){
return first;
}
void list::insert(person* p){
if(first){
first->setNext(new node(p, NULL));
}
else {
first = new node(p, NULL);
}
}
list::~list(){
node* aux;
while (first){
aux = first->getNext();
delete first;
first = aux;
}
}
Okay, so as you can see we have these 3 classes:
person contains an array of 5 people objects, dynamically allocated:
node contains a pointer to next node, and data which contains the actual person object. and,
list that contains the nodes and manages them.
In order to successfully deallocate all the memory, I need call delete listName, this line will go into each node and call delete for each node, which will in itself call the delete for person.
The delete for person will go into each array slot and call the 'delete' of those persons to release that memory.
After that, it will execute the other deletes that are waiting. From bottom to top.
Is this correct? Are my destructors correct?
I would just like to know how to completely release the memory I allocated if there is a singly-linked list that contains nodes that have objects that have dynamically allocated memory.
I'm very confused, my apologies if this is nonsense or utterly bad implementation.
PS: I don't know if this list works, I just wanted to make a basic linked list to see if you guys could help me understand, so hopefully I can grasp the concept on actual, more complex lists. I am aware that there are linked lists and other data structures readily available on libraries but college teachers ask us to do it this way first.
I am a college student and as my final task I have to create AVL Tree dictionary. I am trying to write it myself, I managed to write a lot of it already but I have one problem. When I am using all my getters and setters for random nodes or even vector of them, it works. But when I am trying to setRoot inside of Tree method, it fails. I mean, it works once but once I am trying to work with root calling it with avl.getRoot or as root in my implementation, it fails. My program is crashing. It's the hardest program I ever worked on. Could you solve my problem and give me some hints about important stuff ? Thank you in advance.
Main.cpp - Tests
Node n1("clown",1);
Node n2("cat",1);
Node n3("kid",1);
Node n4("wasp",1);
n1.setLSon(&n2);
std::cout<<"ENG: "<<n1.getLSon().getWord().getEng()<<std::endl;
n1.setRSon(&n3);
std::cout<<"ENG: "<<n1.getRSon().getWord().getEng()<<std::endl;
n1.setParent(&n4);
std::cout<<"ENG: "<<n1.getParent().getWord().getEng()<<std::endl;
if(n2.hasLSon)
n2.getLSon();
else
std::cout<<"n2 does not have a left son"<<std::endl;
AVL_Tree avl;
avl.addNode("cirrus",1);
avl.addNode("monkey",1);
std::cout<<"ENG: "<<avl.branches[0].getWord().getEng()<<std::endl;
std::cout<<"ENG: "<<avl.branches[1].getWord().getEng()<<std::endl;
avl.branches[0].setLSon(&avl.branches[1]);
std::cout<<"ENG: "<<avl.branches[0].getLSon().getWord().getEng()<<std::endl;
avl.branches[1].setParent(&avl.branches[0]);
std::cout<<"ENG: "<<avl.branches[1].getParent().getWord().getEng()<<std::endl;
/*Error is being called here*/
**std::cout<<"ROOT: "<<avl.getRoot().getWord().getEng()<<std::endl;**
}
Tree class : Problematic function
AVL_Tree::AVL_Tree()
{
root=NULL;
}
void AVL_Tree::sort()
{
}
Node AVL_Tree::getRoot()
{
return *root;
}
void AVL_Tree::addNode(std::string eng,int count)
{
int i=0;
branches.push_back(Node(eng,count));
for(i;i<branches.size();i++)
{
if(branches[i].getWord().getEng()==eng)
break;
}
if(branches.size()==1)
{
root=&(branches[i]);
std::cout<<"ROOT DODANY"<<endl;
std::cout<<root->getWord().getEng()<<std::endl;
}
else
std::cout<<"ROOTEM JEST: "<<root->getWord().getEng()<<std::endl;
if(!isBinary());
sort();
}
Tree Class
class AVL_Tree
{
public:
AVL_Tree();
void sort();
void addNode(std::string eng,int count);
void deleteNode(std::string eng);
Node findNode(std::string eng);
Node getRoot();
bool isBinary();
bool isNode(std::string eng);
std::vector<Node> branches;
private:
Node *root;
int leftFactor;
int rightFactor;
};
Node.cpp
Node::Node(std::string eng,int count):word(eng,count)
{
parent=NULL;
l_son=NULL;
r_son=NULL;
hasLSon=false;
hasRSon=false;
}
Node::~Node()
{
parent=NULL;
l_son=NULL;
r_son=NULL;
}
Word Node::getWord()
{
return word;
}
Node Node::getLSon()
{
return *l_son;
}
Node Node::getRSon()
{
return *r_son;
}
Node Node::getParent()
{
return *parent;
}
void Node::setLSon(Node *n)
{
l_son=n;
hasLSon=true;
}
void Node::setRSon(Node *n)
{
r_son=n;
hasRSon=true;
}
void Node::setParent(Node *n)
{
parent=n;
}
Node.h
class Node
{
public:
Node(std::string eng,int count);
~Node();
Word getWord();
Node getLSon();
Node getRSon();
Node getParent();
void setLSon(Node *node);
void setRSon(Node *node);
void setParent(Node *node);
bool hasLSon;
bool hasRSon;
private:
Node *parent;
Node *l_son;
Node *r_son;
Word word;
};
In your addNode you assign a pointer to an element of branches to root. A later call to addNode will add a new branch, reallocate the memory for the vector, and invalidate the root pointer. This results in the later crash when you try to use this invalid pointer.
You also have a semicolon after an if statement at the end of addNode that I don't think you want to be there. Compile with all the warnings turned on to be notified about things like this.
i have a program with 3classes.
first one is for defining a node(my node is an array with 9 elements) - 2nd one contains some functions - 3rd is defining a static stack(I have a stack with 100members that each member is an array with 9members)
suppose that in main(), I call one of the functions from 2nd class(for example expand() ). expand function is supposed to push a node into stack(push into UN) and update the stack pointer. After that for example I want to have access to top node of stack and pop that node using main(). but I'm successful. when I watch the UN and top node through debug tool, I see that their amount is being reset after each push(stack doesn't accept new elements). whats wrong?
here is some parts of code that is needed:
#include<iostream>
using namespace std;
#define max 100
class node
{
public:
int node_n[9];
friend class func;
friend class stack;
};
node n;
class node;
class func
{
public:
func();
void expand(node,stack);
friend class stack;
};
class node;
class stack
{
private:
int sp;//stack pointer
public:
node un[max];//saves expanded noded(children)
stack();
int isempty(); //this will show whether stack is empty or not
int isfull(); //this will show whether stack is full or not
void push(node);
node pop();
};
//****************************
stack::stack()
{
sp=-1;
}
//****************************
int stack::isempty()
{
if(sp==-1)
return true;
else
return false;
}
//****************************
int stack::isfull()
{
return sp==max-1;
}
//****************************
node stack::pop() //un=un-[n]
{
for(int k=0;k<=8;k++)
n.node[k]=un[sp].node[k];
sp--;
return n;
}
//****************************
void stack::push(node n ) //un=un+{x1....xn}
{
sp++;
for(int k=0;k<=8;k++)
un[sp].node[k]=n.node[k];
}
//****************************
void func::expand(node n,stack st)
{
if ( n.node_n[0]==0 )
{
if(n.node_n[1]==0)
{
n.node_n[0]=1;
n.node_n[1]=1;
st.push(n);
.
.
.
//******************************
int main()
{
func b;
stack st;
node n2;
node s; //initial state
node g; //goal state
for(int h=0;h<=8;h++)
{
s.node[h]=0;
g.node[h]=1;
}
//n2=s;
st.push(s);
Lable1:
n2=st.pop();
b.expand(n2,st);
goto Lable1;
system("pause");
return(0);
}
This function
void func::expand(node n,stack st)
is taking the st parameter by value, meaning that it has its own copy of st and any changes it makes will only affect that copy.
What you probably want is to pass st by reference, so that the function can make changes to the original passed in object. To do this, change the function declaration and definition to:
void func::expand(node n,stack &st)
I always seem to get in trouble when I'm deleting all nodes from a tree. I am trying to release all the memory I allocated when creating a trie tree.
I am suppose to create a function remove_all
Is it enough to delete just the "root"
something like this:
void PrefixStringSet::remove_all(NodePtr node)
{
delete root;
}
Or do I have to delete each node with something like this:
void PrefixStringSet::remove_all(NodePtr node)
{
if(!root)
{
return;
}
remove_all(root->children);
delete root;
}
Obviously neither of these are working or I wouldn't be here :).
Other question. Do I have to call the remove_all function in my main function if my destructor is implemented like this
PrefixStringSet::~PrefixStringSet()
{
remove_all(root);
}
Or does the destructor automatically delete the trees/nodes I create?
Edit
struct TrieNode
{
TrieNode(bool present = false);
bool is_leaf();
bool present;
TrieNode* children[ALPHABET_SIZE];
};
class PrefixStringSet
{
public:
// Creates an empty prefix string set.
PrefixStringSet();
~PrefixStringSet();
bool insert(string s);
bool contains(string s);
private:
NodePtr root;
void remove_all(NodePtr node);
};
typedef TrieNode* NodePtr;
Deleting only root is not enough: when deleting a root, you should check whether its children aren't empty, and if they are not empty, recursively delete them. C++ doesn't have garbage collector to do the work for you :)
If your remove_all method is within the destructor of the wrapper object, then you don't have to call it separately.
You should write a remove method in all classes you want to delete at runtime.
So you can delete a tree with little care about garbage collection.
It's easy to use pointer in this way:
class a
{
public:
a(){}
~a(){remove();}
init(int v){
var = new int;
*var=v; }
remove(){delete var;}
private:
int *var;
};
class b
{
public:
b(){}
~b(){remove();}
init(int v){
var = new a;
var->init(v); }
remove(){
var->remove();
delete var; }
private:
a *var;
};
To answer your question: No, deleting root is not enough.
edit: sry i made a mistake at a:init(). I forgot to derefer the pointer.
In Cpp:
void deleteAll(Node* curNode) {
for (int i = 0; i < 26; i++) {
if (NULL != curNode->child[i]) {
deleteAll(curNode->child[i]);
}
}
delete curNode;
}
deleteAll(root);
So I'm trying to create a Singly-linked-list Queue. I'm trying to write a function to add elements, and everything adds fine, but the problem is that its FILO instead of FIFO. I'm not sure how to handle my front and rear pointers.
#include <iostream>
#include <string>
using namespace std;
class Queue{
public:
Queue();
//~Queue();
void add(const string & item);
//string remove();
// unsigned items() const;
void show() const;
private:
struct Node{
string data;
Node *next;
};
Node *rear;
Node *front;
unsigned elements;
};
Queue::Queue():elements(0),rear(NULL),front(NULL){}
//Queue::~Queue(){
//}
void Queue::add(const string & item){
Node *t=new Node;
t->data=item;
t->next=rear;
if(front==NULL)
front=t;
rear=t;
elements++;
}
void Queue::show() const{
Node *p=rear;
for(; p->next!=rear; p=p->next){
cout<<" "<<p->data;
}
cout<<"\n";
}
int main(){
Queue obj;
obj.add("I");
obj.add("Am");
obj.add("Super");
obj.add("Cool");
obj.show();
}
currently it is neither FIFO nor FILO bu JINO (just in, never out).
what you do is to insert on the rear end. and your show does iterate from rear to front, because thats the only linked direction.
for an effective FIFO you would need a remove from the front end of your queue. you will notice, that you can find the front element, but you have no easy way to find the second element that is needed to set the front pointer. this is the drawback of your single linked design, you have to iterate from the rear to the front to find the element pointing to front.
with a single linked list you can do a FILO (actually more likely named LIFO or stack)
for a FIFO a double linked list would be the better design.
if you want to stick to a single linked list you could do some recursion. you eliminate the front pointer cause it is useless.
void Queue::show_one(Node *p) const{
if (p->next!=rear) { // i kept the test for p->next!=rear
// either fix add or test for p->next!=NULL
show_one(p->next);
}
cout<<" "<<p->data;
}
void Queue::show() const{
show_one(rear);
cout<<"\n";
}
likewise you could write a remove()
to achieve, FILO(like STACK?),
When push(add), append your new element at the end( you will deal with rear pointer)
When pop, get rid of the element that rear pointer points to.
In you code, your rear pointer points to one element after end, which is null. So push takes O(n), and also pop cost O(n). Its not efficient. So considering double linked list may be better choice for easy implementation.
I figured out how to reverse the entire thing so it works properly now. Is it efficient? It took 1.06ms to run main.
#include <iostream>
#include <string>
using namespace std;
bool die(const string &msg);
class Queue{
public:
Queue();
~Queue();
void add(const string & item);
string remove();
unsigned items() const;
void show() const;
private:
struct Node{
string data;
Node *next;
};
Node *rear;
Node *front;
unsigned elements;
};
Queue::Queue():elements(0),rear(NULL),front(NULL){}
Queue::~Queue(){
unsigned el=items();
for(unsigned i=0; i<el; i++)
remove();
}
unsigned Queue::items()const{
return elements;
}
string Queue::remove(){
if(front==NULL) die("underflow");
Node *t=front;
string data=t->data;
front=t->next;
delete t;
elements--;
return data;
}
void Queue::add(const string &item){
Node *t=new Node;
t->data=item;
t->next=NULL;
if(front==NULL)
front=t;
else{
Node *t2=rear;
t2->next=t;
}
rear=t;
elements++;
}
void Queue::show() const{
Node *t=front;
for(unsigned i=0; i<items(); i++, t=t->next)
cout<<t->data<<'\n';
}
bool die(const string &msg){
cout<<"Error: "<<msg;
exit(EXIT_FAILURE);
}
int main(){
Queue obj;
obj.show();
obj.add("poo");
obj.add("cra");
obj.add("bil");
obj.add("shi");
obj.show();
cout<<obj.remove()<<"\n";
cout<<obj.remove()<<"\n";
cout<<obj.remove()<<"\n";
cout<<obj.remove()<<"\n";
}