Pop function on Linked list stack - c++

Hello I have a problem to returned variable from my pop function.
I will be happy if you could help me.
The function receives a pointer to the top of the list and should return the answer but I have a problem with a pointer to the list and intger the answer.
Function Code -
int pop(Node* top)
{
Node* tmp = top;
int ans = tmp->next;
top = top->next;
delete tmp;
return ans;
}
Node -
struct Node
{
int num;
Node* next;
}
Node* top = new Node;

The line int ans = tmp->next; appears to be the source of the problem. This is attempting to take the next pointer in the node, convert it to an int, and return it. What you (almost certainly) want is to retrieve the data from the node and return that, with something like int ans = tmp->num;.
Of course, that's not saying the code is perfect otherwise (e.g., it seems to lack any attempt at checking for, not to mention dealing with, errors), but at least with that change, it stands some chance of working correctly under some (ideal) circumstances.

Usually such a function throws an exception if the stack is empty or it has undefined behaviour. I used return value 0 in case when the stack is empty.
int pop( Node * &top )
{
int value = 0;
if ( top )
{
value = top->num;
Node *tmp = top;
top = top->next;
delete tmp;
}
return value;
}
There is another approach when function poo has type void that is when it returns nothing but simply removes the element on the top.

As mentioned in my comment you should split this up to two separate functions. One to get the value, and another one to pop (remove) the Node
void pop(Node*& top) { // Note the reference. You want to change the current top node.
// ^
if ( top ) {
Node *tmp = top;
top = top->next;
delete tmp;
}
}
int& top(Node* top) {
if ( top ) {
return top->num;
}
// Throw an appropriate exception if the stack is empty
throw std::out_of_range("Stack is empty.");
}

First, you are trying to delete tmp node, but top node still exist and value has to be returned as ans or top->next or in this situation top->num. Why do you initialize node tmp in the function when node tmp is a parameter? Why should node * &top be in the function parameters instead of tmp.
value = top->num doesn't fix the problem, because he wants the pointer from the top of the linked list not the random node inputed through the function parameters. To fix this problem Node * tmp should equal top and then value should be equal to tmp->num. Otherwise all other problems have been fixed.
//EDIT
Ignore everything before //edit because all that is questions about his question that I now already know. I have compiled this code and it completely worked for me.
struct Node
{
int data;
Node *next;
};
int pop(Node *head)
{
while(head->next != NULL)
{
head = head->next;
}
int value;
Node *tmp;
tmp = new Node;
value = head->data;
tmp = head;
delete tmp;
return value;
}
Compiled code link - http://ideone.com/7EgBhf

Related

Why am I getting this runtime error: member access within null pointer of type 'Solution::node' (solution.cpp)

I was solving a question on leetcode 1409. Queries on a Permutation With Key, but I am getting this runtime error I don't know why. I am unable to debug this error.
Problem Statement:Given the array queries of positive integers between 1 and m, you have to process all queries[i] (from i=0 to i=queries.length-1) according to the following rules:
In the beginning, you have the permutation P=[1,2,3,...,m].
For the current i, find the position of queries[i] in the permutation P (indexing from 0) and then move this at the beginning of the permutation P. Notice that the position of queries[i] in P is the result for queries[i].
Return an array containing the result for the given queries.
My approach: I created a linkedlist to store the integers form 1 to m.
Then according to each query, I pass it to a function getpos() which returns the position of that query in the list and then updates it as per the directions given in problem statement.
This return value is then added to a result vector which is supposed to be the final answer after all queries are processed.
I have added comments to better understand my code
class Solution {
public:
struct node {
int data;
node* next = NULL;
};
node* addnode(node* head, int data) {
if(head == NULL) {
head = new node;
head->data = data;
}
else {
node* temp = head;
while(temp->next != NULL) { temp = temp->next; }
temp->data = data;
}
return head;
}
int getpos(node** head, int data) { //To get position of given query
int count = 0;
node* temp = *head;
node* prev;
while(temp->data != data) { //runtime error:member access within null pointer of type 'Solution::node' (solution.cpp); SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:32:21
prev = temp;
temp = temp->next;
count++;
}
prev->next = temp->next; //searched node deleted
temp->next = *head; //add the searched node to beginning of the list
*head = temp; //udapate head
return count; //we have position stored in count;
}
vector<int> processQueries(vector<int>& queries, int m) {
node* head = NULL;
for(int i=0;i<m;i++) { head = addnode(head,i+1); }
int n = queries.size();
vector<int> result;
for(int i=0;i<n;i++) { result.push_back(getpos(&head,queries[i])); }
return result;
}
};
Please debug and explain the cause of the error. I face many runtime errors which I fail to debug.
Your add_node function is bugged. Just take a deep breath and look at the code. add_node should allocate a node using new every time it is called. Ask yourself how many times and under what circumstances your version allocates a new node?
I'm sure you can see that your code only allocates a new node when head equals NULL, therefore it must be bugged.
Incidentally if you wanted a linked list why didn't you use std::list? You would have avoided the mistake you made.

C++ why is creating a new node to delete a node on a stack wrong

I'm learning about singly linked list stacks in class and I came across this stackoverflow page that gave me some reference on how to pop a node:
Pop function on Linked list stack
The first answer uses the following code to pop off a node:
struct Node
{
int data;
Node *next;
};
int pop(Node *head)
{
while(head->next != NULL)
{
head = head->next;
}
int value;
Node *tmp;
tmp = new Node;
value = head->data;
tmp = head;
delete tmp;
return value;
}
the third answer uses the following code:
int pop( Node * &top )
{
int value = 0;
if ( top )
{
value = top->num;
Node *tmp = top;
top = top->next;
delete tmp;
}
return value;
}
now, because of the first answer I originally wrote my pop function like so:
// Pop the top element off of the stack and return its value.
StackElement Stack::Pop()
{
assert (!Empty());
StackElement poppedData = tos->data;
Node *temp = new Node;
temp = tos;
tos = tos->next;
delete temp;
return poppedData;
}
but, my teacher said that creating a new node to delete a previous node will cause a memory leak.
Ultimately I rewrote my code to match style two like so:
StackElement Stack::Pop()
{
assert (!Empty());
StackElement poppedData = tos->data;
Node *temp = tos;
tos = tos->next;
delete temp;
return poppedData;
}
Can anyone explain to me why the first implementation is wrong? I'm surprised nobody commented on this when the person posted it on the other stackoverflow question. It seems to me like I'm creating a pointer temp of type Node that points to a new Node (aka new memory address), and then I'm setting the value of that memory address to the value in the top of the stack's memory address. I move the top of stack to the next node, and then delete this temp node I created, but because I declared it as a new Node that just has the value of the old top of stack, it doesn't actually have any relation to that node. The old top of stack node is removed from the stack but the memory is not properly freed. Is this correct?
The first answer is wrong.
tmp = new Node;
value = head->data;
tmp = head;
delete tmp;
This deletes the head pointer, which is what you want. But the function creates a new memory allocation at tmp and then immediately overwrites the pointer with the value head. You have now lost the pointer to the allocated data. This is a memory leak.

Doubly Linked List adding elements

I've a uni assignment and unfortunately, encountered a problem.
I'm still struggling with pointers and references so it's quite hard for me to find a solution, even though I've searched for it for an entire day.
Here are essential parts of my code:
struct BuenoList
{
int value;
BuenoList* prev;
BuenoList* next;
};
Declaration:
void insertNode(BuenoList*, int);
Definition:
void insertNode(BuenoList* tail, int _id)
{
BuenoList* temp = new BuenoList;
temp->value = _id;
temp->prev = tail;
tail->next = temp;
tail = temp;
tail->next = NULL;
}
Now, in main() I do this:
int main(int argc, char **argv)
{
BuenoList* BuenoListing = new BuenoList;
BuenoListing->value = 1;
BuenoListing->prev = NULL;
BuenoListing->next = NULL;
BuenoList* BuenoHead = BuenoListing;
BuenoList* BuenoTail = BuenoListing;
insertNode(BuenoTail, 2); // Add value 2 to the list
insertNode(BuenoTail, 3); // Add value 3 to the list
return 0;
}
Okay, so here's the problem:
When I print the list from the first element it prints like this:
1
1 2
1 3
So apparently this line
insertNode(BuenoTail, 3);
overwrites value 2.
My guess would be that BuenoTail does not change so there must be a problem with the reference.
How can I solve this?
Print should be: 1 2 3
#EDIT
void deleteNode(BuenoList*& tail, int _id) // Search list for specified value and delete it
{
BuenoList* temp = tail;
while (temp->prev != NULL)
{
if (temp->value == _id) break;
else temp = temp->prev;
}
if (temp->value == _id)
{
temp->prev = temp->next;
free(temp);
}
else std::cout << "ERROR KEY DOES NOT EXIST\n";
}
Considering you wanted to keep your code structure the same, I will show you two possible solutions. In a C fashion, you can use a pointer to a pointer to update your head and tail pointers. Or, in C++ you can pass your head and tail pointers by reference. Personally, in C++ I would make a LinkedList class that keeps track of your head and tail nodes though.
Passing pointer by reference (C++)
In order to pass your pointer by reference, first change your insertNode declaration,
void insertNode(BuenoList *&tail, int _id);
Next, change your insertNode definition with the same function arguments. That is it, your code should work now. This minute change works, because your tail node in the insertNode function is aliased with the tail node in your main function.
Passing pointer by pointer (C)
I know you put a C++ tag, but you can also update your head and tail nodes using a more C like method. First, in the main function, you will need to declare BuenoHead and BuenoTail as a pointer to a pointer.
int main(int argc, char **argv)
{
BuenoList* BuenoListing = new BuenoList;
BuenoListing->value = 1;
BuenoListing->prev = NULL;
BuenoListing->next = NULL;
BuenoList** BuenoHead = new BuenoList*;
BuenoList** BuenoTail = new BuenoList*;
*BuenoHead = BuenoListing;
*BuenoTail = BuenoListing;
insertNode(BuenoTail, 2); // Add value 2 to the list
insertNode(BuenoTail, 3); // Add value 3 to the list
return 0;
}
Then you need to update the insertNode function declaration to take a pointer to a pointer.
void insertNode(BuenoList** tail, int _id);
Then, you need to update the function definition to deference your pointer to a pointer correctly,
void insertNode(BuenoList** tail, int _id)
{
BuenoList* temp = new BuenoList;
temp->value = _id;
temp->prev = *tail;
temp->next = NULL;
(*tail)->next = temp;
*tail = temp;
}
EDIT
Deleting a node
You modified your question, asking for help on deleting a node. You have several problems with your deleteNode function.
You mix new with free. Whenever you allocate with new, you should correspondingly use delete.
You call temp->prev without checking whether temp could be NULL or not.
You need to change the function arguments to include your head pointer. It might turn out the node you want to delete is the head of your linked list. If so, you'll need to update the head node accordingly.
You need to check whether the node you are deleting is in the middle of the list, the head of the list, the tail of the list, or if is is the only node of the list. Each of these cases requires different operations to update your linked list.
Considering this is a university assignment, I don't want to give you the full blown solution. Here is a partially modified deleteNode function. I left some parts for you to fill out though. Hopefully that helps. Maybe next time focus the question a bit more, so I don't have to give a partial solution.
void deleteNode(BuenoList*& tail, BuenoList*& head, int _id) {
BuenoList* toDelete;
toDelete = tail;
// Traverse list and find node to delete
while( ( toDelete != NULL ) && ( toDelete->value != _id ) ) {
toDelete = toDelete->prev;
}
// If node not found, return
if( toDelete == NULL ) {
std::cout << "ERROR KEY DOES NOT EXIST\n";
return;
}
// Check to see if node to delete is tail
if( toDelete == tail ) {
if( toDelete->prev != NULL ) {
tail = toDelete->prev;
tail->next = NULL;
} else { //Deleting only node in list
tail = NULL;
head = NULL;
}
delete toDelete;
return;
}
// Check to see if node to delete is head
if( toDelete == head ) {
// FILL OUT WHAT TO DO HERE
return;
}
// Node to delete is neither head nor tail.
// FILL OUT WHAT TO DO HERE
return;
}
You are updating tail within insertNode(), but the updated value is not communicated back to the caller in any way. So BuenoTail does not change, as you suspected.
One easy way to fix that is to change your function to:
BuenoList *insertNode(BuenoList* tail, int _id)
and return the new tail from that function. Also change the calls to
BuenoTail = insertNode(BuenoTail, 2); // Add value 2 to the list
You may want to consider using a node structure and a list structure:
struct BuenoNode
{
int value;
BuenoNode* prev;
BuenoNode* next;
};
struct BuenoList
{
BuenoNode* head;
BuenoNode* tail;
size_t count; // having a count would be optional
}
The list functions would take a pointer to the list structure, such as InsertNode(BuenoList * blptr, int data); The list structure would be initialized so that both head and tail pointers == NULL, and you'll need to check for adding a node to an empty list or removing the only node in a list to end up with an empty list.

Why isn't my remove node function working?

I've checked the boards and could not find any help with this. I find it easy to implement recursive functions given base and general cases, but this doesn't work the way I do it. I'm supposed to iterate down a list until I reach the tail of a linked list. If the next node is NULL, then I have to store the value at the last node, remove that node, and return the value. So it's similar to a dequeue method, except it's performed recursively. What am I doing wrong?
int LinkedList::removeTailRec(Node *n)
{
// check for the base case(s)
if(n->next == NULL)
{
Node *tmp = new Node();
tmp = n;
int val = n->value;
tmp = NULL;
return val;
}
else
return removeTailRec(n->next);
// else call the recursive method
}
First, I recommend you use nullptr instead of NULL.
Then, onto your code. You're actually not removing anything from your list.
if(n->next == NULL)
{
Node *tmp = new Node();
^^^^^^^^^^
//Useless, and dangerous. This memory is never free'd
tmp = n;
int val = n->value;
tmp = NULL;
^^^^^^^^^^
//You just set a local variable to NULL, you're not deleting anything
return val;
}
If you want to remove the node, you'll have to keep a reference to the previous node (e.g. having a doubly linked list, that is, having a pointer to the next element and a pointer to the previous element in each node, or working on the previous node directly).
Set this previous node's next to nullptr, store the node's value and then delete the Node pointer.
One way to do this is to work with the pointer to the next node :
int LinkedList::removeTailRec(Node *n)
{
//EDIT: Adding a check for n validity
if(!n){
//Here, you should have a way of detecting
//a call to your method with a null pointer
return 0;
}
Node* nextNode = n->next;
// check for the base case(s)
if(nextNode->next == nullptr)
{
//Get the next node value
int val = nextNode->value;
//Set the current node next member to nullptr
n->next = nullptr;
//Free the last node
delete nextNode;
return val;
}
else{
return removeTailRec(n->next);
}
// else call the recursive method
}
You are storing the result but not deleting it from linked list. You can return result in another variable (pointer : result).
Node* getTail(Node *n,int *result){
//u can even free the memory
if(!n->next)
{
result=n->value;
return NULL;
}
n->next=getTail(n->next,result);
}
or you can do it other way
int getTail(Node *n)
{
if(!n) return 0;
if(n->next)
{
if(!n->next->next)
{
Node *frnode=n->next;
int result=n->next->value;
n->next=NULL;
delete frnode;
return result;
}
getTail(n->next);
}
You are not removing last node in your code, and you leak another (temporary) node here.
To remove last node you have to zero the link in the previous node.
Your code should look like
...
if (n == NULL || n->next == NULL)
throw std::out_of_range("node");
if(n->next->next == NULL)
{
int val = n->next->value;
delete n->next;
n->next = NULL;
return val;
}
else ...
Be aware of the fact that c++ is not a functional language and has no optimizations for tail recursion, so in real application as your lists grow big enough you'll eventually have failure with stack overflow =) use Haskell or Erlang for this style of programming, in c++ use for or while.
You should set the Node n's previous Node's next field to NULL when n is the tail Node.

Simple Linked List Implementation in C++

I'm a programming student in my first C++ class, and recently we covered linked lists, and we were given an assignment to implement a simple one. I have coded everything but my pop_back() function, which is supossed to return a pointer to the Node that needs to be deleted in Main(). No Node deletion is to be done in the actual function. So my question is:
Would you be willing to help point me in the right direction for my pop_back() function? Also, if you notice anything else that I'm doing wrong, let me know.
Also, this linked list is just to work with strings. In this case, a grocery list, so one string for the quantity of the item(1,2), and one string for the item type. (Milk, Eggs, etc.)
Below I've included my List & Node class implementations, so you can get an idea of what I've done so far.
Node.cpp
Node::Node(void)
{
descrip = " ";
quantity = " ";
previous = NULL;
next = NULL;
}
Node::Node(string q, string d)
{
descrip = d;
quantity = q;
previous = NULL;
next = NULL;
}
Node* Node::GetNext()
{
return next;
}
Node* Node::GetPrevious()
{
return previous;
}
void Node::SetNext(Node * setter)
{
next = setter;
}
void Node::SetPrevious(Node * setter)
{
previous = setter;
}
List.cpp
List::List(void)
{
first = NULL;
last = NULL;
numNodes = 0;
}
Node* List::GetFirst()
{
return first;
}
Node* List::GetLast()
{
return last;
}
void List::SetFirst(Node* setter)
{
first = setter;
}
void List::SetLast(Node* setter)
{
last = setter;
}
int List::GetNumNodes()
{
return numNodes;
}
void List::push_front(Node* item)
{
if (first == NULL)
{
first = item;
last = item;
}
else
{
Node* pFirst = first;
item->SetNext(pFirst);
first = item;
numNodes++;
}
}
void List::push_back(Node * item)
{
if (last == NULL)
{
first = item;
last = item;
}
else
{
last->SetNext(item);
last = item;
numNodes++;
}
}
Node* List::pop_front()
{
Node* temp = first;
first = first->GetNext();
if (first == NULL)
{
temp = first->GetNext();
first = p;
}
if (first == NULL)
{
last = NULL;
}
if (numNodes > 0)
{
numNodes--;
}
return temp;
}
Node* List::pop_back() // this whole function may be wrong, this is just my attempt at it
{
Node* temp;
temp = first;
while((temp->GetNext()) != NULL)
// im stuck here
}
Some pointers:
0x1243bfa3
0x45afc56e
0xdeadbeef
Some more pointers:
You should prefer to initialize your class members in the initialization list, not in the constructor's body.
In C++, unlike C89, we declare and define a function with no parameters as void f();, not void f(void);.
In C++ we commonly reset pointers with 0, not NULL.
See below for what I mean in code.
Good C++ code will try to take advantage of RAII. This implies avoiding primitive pointers for the most part. In this case plain old std::auto_ptr<> would make a perfectly sufficient substitute for the primitve Node* pointers. However, I do reckon part of the exercise here is pointer arithmetics, and so I just leave this as a side-note.
It would be useful for us if you'd attach the class declarations. I assumes all those accessors and mutators, GetFirst() and SetFirst() etc., are there because they are public. That's a bad idea. First, they expose the private pointers, which defeats the whole point of accessor. Second, they don't do anything special so they're just extra code -- which means extra room for bugs. This brings me to the next point.
Your mutators are incorrect. You blindly assign a new value to the private member pointer, without deleting what you had before. That's a memory leak.
Ever tried to pop_front() when the list is empty?
Finally, 8 being a round number it's time we get to the question at hand. pop_back(). My question to you is, why are you traversing the list all the way to the end if you so meticulously maintain a pointer to the last node of your list? Indeed, if you wouldn't bother with maintaining a pointer to the end of the list then you'd have to traverse all the way to the last node in order to pop it. And for that you were in the right direction. Except that ...
When you access members through pointers, as in first->GetNext(), always make sure first isn't a null pointer -- or else state in the function's documentation comment that you assume the pointer is not null.
These should get you started.
Points 1, 2 and 3 in code:
Node::Node()
: descrip(" "), quantity(" "), previous(0), next(0)
{
}
So if I understand this right you just want to run through your linked list until you get to the last node in the linked list and return the pointer to it?
I'm pretty sure what you have there will do it except
Node* List::pop_back() // this whole function may be wrong, this is just my attempt at it
{
Node* temp;
temp = first;
while(temp->GetNext() != NULL)
{
temp = temp->GetNext();
}
return temp;
}
So if I read it right, there it will continually loop around until it gets to the node with none in the line behind it, then return it.
I like the previous posters answer, but one thing you might want to keep in mind is if you have an empty list. Then your first pointer will equal NULL and you would be trying to call NULL->GetNext() basically and Seg Fault. I think you can edit the above code slightly and still get have it work like this:
Node* List::pop_back()
{
Node* temp;
temp = first;
while(temp != NULL && temp->GetNext() != NULL)
{
temp = temp->GetNext();
}
return temp;
}
This will have the function return NULL if there is nothing in the list and still work properly.
It would definitely have helped me if you also had posted your class declaration. I cannot guarantee that the below is correct but it makes sense to me
Node* List::pop_back()
{
Node *temp = NULL;
if(numNodes == 1)
{
temp = first;
// setting the list pointers to NULL
first = NULL;
// setting the list pointers to NULL
last = NULL;
//You should also probably remove the links from your node
//to the next and previous nodes but since you didn't specify
//this it is up to you
numNodes--;
}
else if(numNodes > 1) //more than one element
{
//the pointer you want to return
temp = last;
//For clarity I am creating another variable here
Node *newLast = temp->GetPrevious();
//Setting the new last node to point at nothing so now temp
//is "disconnected from the list"
newLast->next = NULL;
//the last pointer of the list is now pointing at the new last node
last = newLast;
//You should also probably remove the links from your node
//to the next and previous nodes but since you didn't specify this it is up to you
numNodes--; //decrement the counter
}
return temp;
}