Custom Queue Class C++ - c++

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";
}

Related

Implementing a Stack in C++ using a linked list

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).

Linked list overwrites the previous value

I want to create a linked list with classes. I have two classes, one LinkedList and another LinkedNode. My problem is that my function InsertAtEnd always delete the current node. So when I want to print my linked list, I can't see anything.
I know thanks to debugger that in the function InsertAtEnd, we don't enter in the while loop, this is the problem. But after several attemps I can't resolve my problem.
This is my code:
void LinkedList::InsertAtend(int data)
{
LinkedNode* node = new LinkedNode();
node->setData(data); node->setNext(nullptr);
LinkedNode* tmp = _header;
if (tmp != NULL)
{
while (tmp->getNext() != nullptr)
{
tmp = tmp->getNext();
}
tmp->setData(data);
tmp->setNext(nullptr);
}
else
{
_header = node;
}
}
My class LinkedNode:
class LinkedNode
{
public:
LinkedNode();
~LinkedNode();
void setData(int data);
void setNext(LinkedNode* next);
int getData() const;
LinkedNode* getNext() const;
private:
int _data;
LinkedNode* _next;
};
My class LinkedList:
#pragma once
#include
#include "LinkedNode.h"
using namespace std;
class LinkedList
{
public:
LinkedList();
~LinkedList();
void PrintList();
void InsertAtend(int data);
void PrintList() const;
private:
LinkedNode* _header;
};
Thanks for your help !
tmp->setData(data);
Your tmp is not the node that you're trying to add, but the last in your list.
tmp is the last Node, so if you don't want to delete it you shouldn't write value data in it. You should link it with the new Node, which you named node.
Instead of
tmp->setData(data);
tmp->setNext(nullptr);
You should write
tmp->setNext(node)
At the end of the loop, the tmp is the last node in the current list. As you want to add the new node after the last node, you need to
tmp->setNext(node);
to append it (and not set the data as the data are already set to the new node).
Also note that you actually do not need to iterate through the entire list at all, if you keep another member variable to the current end of the list (_tail). Then you can access it directly and simply append and update.

C++ Pointers, references and AVL Tree

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.

How to initialize a Queue (linked list) and insert an element?

I have an assignment where I have to create a linked list and add and remove items from it. I'm having a problem understanding how to initialize the linked list in my constructor and adding items to it as well.
Here's my header file for it.
#ifndef CONGERA3_H
#define CONGERA3_H
const int MAX_STRING = 6;
typedef char Element300[MAX_STRING + 1];
class Queue300
{
public:
Queue300 ();
Queue300 (Queue300 &old);
~Queue300();
void enQueue300 (const Element300);
void deQueue300 (Element300);
void view300();
private:
struct Node300;
typedef Node300 * NodePtr300;
struct Node300
{
Element300 element;
NodePtr300 next;
};
NodePtr300 front, rear;
};
#endif
Here's my implementation file as well. I've removed the other functions for now, I feel like if I can get the constructor and enQueue down I can figure out the rest of them.
#include <iostream>
#include "congera3.h"
using namespace std;
Queue300::Queue300 ()
{
front = NULL;
return;
}
void Queue300::enQueue300 (const Element300 element)
{
Node300 temp;
temp.element = element;
}
I feel like I need to add a lot more to the constructor, such as setting the rear to point to the front. In the enQueue I think I need to have rear point towards the element I'm passing in and then have that element's next point towards front.

Searching for a node in a tree structure

I need help finding and returning a "node" in a general tree structure. Each node can have more than 2 children so it's not a binary tree. I've been given the following code, this Element object has a list to contain its children, I create one element node pointer in main and using that I have to add and search for children. This is for a school project but I'm not looking for answers (an answer wouldn't hurt). Any advice on how to go about this problem would be much appreciated, thanks!
#pragma once
#include <iostream>
#include <list>
#include <sstream>
using namespace std;
class Element
{
private:
list<Element*> children;
char* _tag;
int _value;
// private methods
public:
// default constructor
Element();
// non-default constructors
Element( char* name); // value is set to -99 if not given
Element(char* name, char* value);
// destructor, must recursively destruct its children
// and release the memory allocated for _tag
~Element();
// ostream operator ( pre-order traversal)
friend ostream& operator << (ostream& out, const Element& E);
void display_xml(); // print out the tree in xml-- format
void addChild( Element* child); // add a child
// Find the first element such that _tag == tag
// returns “this” pointer of this element
Element* findTag( char* tag);
char* getName();
int getValue();
void setName(char* name);
void setValue( int value);
int height(); //b return the height
int size(); // return the size
// other methods
};
this is my best attempt at a solution, it has obvious problems but I'm new to all of this and some explanation on a proper solution, or some sample code would be very helpful!
Element* Element::findTag(char* tag)
{
list<Element*> temp = children;
int s = temp.size();
if(getName() == tag)
{
return this;
}
else
{
for(int i = 0; i < s; i++)
{
findTag((*temp.front()).getName());
temp.pop_front();
}
}
}
I will give you a pseudo-code for searching for a node that has a value val in a tree rooted at root:
find(Node root, val)
if(root.value == val) return root //-- if the recursion found the node we are searching for
else
for every child x of root //-- re-cursing on the children of root
if(find(x, val) != null) return x //-- if one of the calls found the node we are searching for
return null //-- if we did not find the node we want in the sub-tree rooted at root