hey i am trying to add to my queue but I have a problem, and I need some help
i used a linked list for my queue and the problem is when I add a 3rd item to my list I overwrite the second
this is the code
void addnode(node* data)
{
if (begin == NULL)
{
data->next = begin;
begin = data;
}
else
{
end = data; //this is where the problem when i add a 3rd data i dont save anywhere my end so its gone
begin->next = end;
end->next = NULL;
}
}
in my code i have begin for the start of the queue, and end for the end of it
the linked list i built is with classes in c++,
but whenever i add a 3rd data the second gets overwriten so i always have two..
I need some help with how to fix it, thanks :)
edit this is more of the code: this is my class for the queue
#include"node.h"
class queue
{
public:
queue();
~queue();
void addNode(node*);
private:
node* begin;
node* end;
};
this is the class that i get the data from
using namespace std;
class node
{
friend void printclient(node &);
public:
node();
~node();
void setstr(string);
void setmoney(int);
node* next;
private:
string name;
double money;
int id;
};
The function can look the following way. I suppose that the data member next of the node pointed to by the pointer data is already set to nullptr.
void addnode(node* data)
{
if (begin == nullptr)
{
begin = end = data;
}
else
{
end = end->next = data;
}
}
That is if the queue is empty (the pointers begin and end are equal to nullptr) then begin and end are set to the added pointer.
Otherwise the new node is appended to the end of the queue. In this case the data member next of the node pointed to by the pointer end is set to the new pointer and this pointer becomes the end pointer.
Pay attention to that the user of the queue should know nothing about the class node. The class should be declared as a private or protected member of the class queue. And the method addNode should be substitute for the method push declaration of which should look like
void push( const std::string &name, int id, double money );
Related
I am trying to create an appendToTail function which will add a node to the end of a singly linked list.
I am having trouble in adding a node if the head is NULL(the linked list is empty)
class Node {
private:
Node* next;
int data;
public:
Node(int d, Node* n = NULL)
: data(d)
, next(n)
{
}
void appendToTail(int);
//other trivial functions(getters and setters etc. ) defined and
//declared
};
void Node::appendToTail(int d)
{
Node* end = new Node(d);
Node* n = this;
if (n == NULL)
n = end;
else {
while (n->next != NULL)
n = n->next;
n->next = end;
n->next->next = NULL;
}
end = NULL;
delete end;
}
int main()
{
Node* n = NULL;
n->appendToTail(5);
std::cout << n->getData(); //getData() is a function which
//retrieves the Data member variable
}
I am expecting to get 5 but I am getting an error which appears to be caused because my node remains null.
Now with modern C++ idioms we use smart pointers instead of raw pointers, it gives you the benefit of RAII (Resource acquisition is initialization) mechanism. In addition if you want an elegant solution to your problem you should introduce a List class with which you can express more clearly the concept of an empty list. It would give something like this:
#include <memory>
#include <iostream>
class List
{
public:
class Node
{
private:
std::shared_ptr<Node> next;
int data;
public:
Node(int d):next(nullptr),data(d){}
inline int getData() const {return data;}
inline std::shared_ptr<Node> getNext() const {return next;}
friend List;
};
List():head(nullptr),tail(nullptr){}
void appendToTail(int );
inline std::shared_ptr<Node> getHead() const {return head;}
inline std::shared_ptr<Node> getTail() const {return tail;}
private:
std::shared_ptr<Node> head;
std::shared_ptr<Node> tail;
};
void List::appendToTail(int d)
{
auto newTail = std::make_shared<Node>(d);
if (head == nullptr)
{
head = tail = newTail;
}
else
{
tail->next = newTail;
tail = newTail;
}
}
int main()
{
List l;
l.appendToTail(5);
std::cout<<l.getHead()->getData();
}
But you should definitely prefer std::list<T> or std::vector<T>.
Unfortunately there several errors with your approach. Semantic errors and a logical error with your interpretation of a linked list. Let's start with your initial misunderstanding. You cannot add a new tail to an empty list. Because it is emtpy. Meaning, not yet existing. Only if some object is existing/instantiated you can add a tail. You cannot add something to not existing stuff. So your idea to start with a Node* n = nullptr cannot work logically.
Additionally you are dereferencing a nullptr (major bug). That is also the main problem of your code. Nothing works. You need an instantiated object, before you can call it's member functions.
So before you can populate the list, you need to create/instantiate it initially. So you need to explicitly create the first node in your main function with
Node* n = new Node (5)
Then the list is existing and from now on you can add new members with calling appendToTail.
There are more semantic errors in your code which have luckily no side effects.
You must not delete the 'end' variable in your function. You want to keep the newly allocated memory for the new tail. But you introduced an additional sematic error by setting 'end' to nullptr and then call delete. Deleting a nullptr is a noOp and will do nothing. So, although you have a semantic error, this will not cause any trouble.
There is more:
For a pointer to Null you should always use nullptr.
And, your
if (n == NULL)
is always false. Before that, you assigned this to n. This is never NULL. You can delete the if else. Keep the statements from the else, except the
n->next->next = NULL;
That's not necessary. The constructor did that already for you. As explained, the next 2 statements should also be elimanted.
Additionally you may want to read a little more on the concept of linked lists.
I hope I could help a little
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.
This code is copied from the c++ primer plus. I think some
steps in the dequeue function is unnecessary. But the book
say it is important.I don't understand. I hope some one can show me more detail explanation.Here is the definition of the queue.
typedef unsigned long Item;
class Queue
{
private:
struct Node{ Item item; struct Node * next; };
enum{ Q_SIZE = 10 };
Node * front;
Node * rear;
int items; // the number of item in the queue
const int qsize;
Queue(const Queue & q) :qsize(0){};
Queue & operator=(const Queue & q){ return *this; }
Queue & operator=(const Queue & q){ return *this; }
public:
Queue(int qs = Q_SIZE);
~Queue();
bool isempty()const;
bool isfull()const;
int queuecount()const;
bool enqueue(const Item & item);
bool dequeue(Item & item);
};
bool Queue::dequeue(Item & item)
{
if (isempty())
return false;
item = front->item;
Node * temp;
temp=front; // is it necessary
front = front->next;
items--;
delete temp;
if (items == 0)
rear = NULL; //why it is not front=rear=Null ;
return true;
}
The nodes in this queue are stored as pointers. To actually create a node some code like Node* tmp = new Node() is probably somewhere in the enqueue-Function.
With front = front->next; the pointer to the first element gets moved to the next element in the queue. But what about the previous front-node? By moving the pointer we "forget" its adress, but we don't delete the object or free the memory. We have to use delete to do so, which is why the adress is temporarily stored to call the delete. Not deleting it would cause a memory leak here.
About your second question: The frontpointer has already been moved to front->next. What could that be if there was only one element inside the queue? Probably NULL, which should be ensured by the enqueue-function. ("Note: If you are managing this code, it is a good idea to replace NULL with nullptr).
The only variable that didn't get updated yet is rear.
temp = front;
saves a pointer to the front element so it can be deleted after front has been modified.
If the queue is empty, front = front->next; has already set front to null, so there's no need to do it again.
I have a one-dimensional template list that contains nodes, each node has a link to next node.
It works rather well on it's own, but not when it contains another linked list.
LinkedList and Node looks something like that:
template <class T>
class LinkedList
{
private:
Node<T>* pPreHead;
public:
LinkedList(void);
~LinkedList(void);
Node<T>* getHead(void);
int size();
void addElementToEnd(T& value);
void deleteNextNode(Node<T>* pNodeBefore);
}
template <class T>
class Node
{
private:
T value;
Node* next;
public:
Node();
Node* getNext();
Node* getValue();
void setNext(Node* nextElem);
void setValue(T elem);
};
Now for the task I need to use LinkedList>, which is filled via a loop.
It looks something like this:
ifstream fl;
fl.open("test1.in", std::ifstream::in);
while (fl.good())
{
string currentLine;
getline(fl, currentLine);
LinkedList<string> newDNA;
//newDNA being filled here so I skipped code
DNAStorage.addElementToEnd(newDNA);
//Place 1
}
//Place 2
Now if I insert some test output code in "Place 1" everything is fine, but when the loop enters new iteration newDNA variable gets freed and so is the pointer inside DNAStorage (which is LinkedList<LinkedList<string>> in question), and when I try to print anything in "Place 2" I get segmentation fault.
Unfortunately I can't use any other data structures since this is the kind of task I need to do.
My question is - how can this be fixed, so that it actually is not freed prematurely?
Edit:
Here's my code for AddElementToEnd(T& value):
template <class T>
void LinkedList<T>::addElementToEnd(T &value)
{
Node<T> *newtail = new Node<T>;
newtail.setNext(NULL);
newtail.setValue(value);
if(pPreHead == NULL)
{
pPreHead = newtail;
return;
}
Node<T> *tail = pPreHead;
while(tail.getNext() != NULL)
{
tail = tail.getNext();
}
tail.setNext(newtail);
}
The problem is that you are storing references to objects that are going out of scope, causing undefined behavior when you try and access them. Your LinkedList<string> newDNA gets created and destroyed with each iteration of the while loop, yet you pass a reference to be stored in DNAStorage list.
One solution would be to store a copy of each object (not reference) in the list when addElementToEnd() gets called.
I have a class of events.
Now All I have to do is to create events and store them in a linked list. but I don't know how to fix the head position. I mean if i define head to be NULL in a constructor then for every new event it would re-defined to be NULL. Thus I will have only one event in my linked list.
My code is something like this:
// event.h
class event{
private:
Event *head;
Event *nxt;
int date;
string name;
public:
event();
event(int d, string n);
Add_item();
}
//event.cpp
event::event(){}
event::event(int date, string name): date(date), name(name){
head=NULL;
// Now each time I call a constructor, head would be re-defined as NULL.
What should I do???
First off, the code shows that class Event is self-contained. Which is to say that head and nxt are part of the object itself. If you wish to use a Linked List of objects linking to each other but not maintaining the head outside then I would do the following...
// event.cpp
event::event() {
head = NULL;
}
event::event(int date, string name): date(date), name(name) {
head = NULL;
}
event::event(event *prev, int date, string name): date(date), name(name) {
if (prev->head != NULL) {
this->head = prev->head;
} else {
prev->head = this->head = prev;
}
prev->nxt = this;
this->nxt = NULL;
}
An example of using this would be as follows:
event *tailEvent = new event(1, 'first');
event *nextEvent = new event(tailEvent, 2, 'second');
event *thirdEvent = new event(nextEvent, 3, 'third');
...
tailEvent = lastEvent;
and so on and so forth. So, tailEvent->head will always point to the first created event and the tailEvent->nxt will follow in the list.
BUT... This is highly prone to errors, so I would recommend keeping the list itself outside, if possible using STL. See Learning C++: A sample linked list for an example.
EDIT:
Better approach:-
class Event {
private:
Event *next;
int date;
string name;
public:
Event() {};
Event(int date, string name) : date(date), name(name) {};
setNext(Event *next) { this->next = next; };
int date() { return date; };
string name() { return name; };
Event *next() { return next; };
};
class EventList {
private:
Event *head;
public:
EventList() { head = NULL };
void add(int date, string name);
Event *head() { return head; }
}
void EventList::add(int date, string name) {
Event *newEvent = new Event(date, name);
newEvent->setNext(NULL);
Event *tmp = head;
if (tmp != NULL) {
while (tmp->next() != NULL) tmp = tmp->next();
tmp->setNext(newEvent);
} else {
head = newEvent;
}
}
You need some controlling code for your list. List items cannot control themself.
I would recommend you use a container std::list which implements all list operations.
If you want to implement your list, you should create controlling class, eg EventContainer and implement insert/delete and search operations.
A better approach is to have two classes here: One to store each event and another to manage and store information about the list.
There will be many event classes in your list. There will only be one list class.
Now, your event class will in fact need some helper methods such as next and previous pointers. You can implement them directly or create a third class that is either inherited from or have it contain the event class.
But either way, the class that manages the list should only require one instance. And in that instance the head can be initialized to null, and it will be updated as needed.