Circular Singly Linked List: Remove a particular Node from List - c++

I wrote the code to remove a particular node from list according to user
choice, code works perfectly fine for a particular value but if i make
several calls to it meaning if I call it 2 times continuously then one of my
another function pointer_to_node(index) gives an out of bounds error which
was also implemented by me to record such conditions,
Actually, why I need several calls is that I have to write a separate function
to remove all the nodes. I am trying to accomplish that task using this
function by using a for loop up to the size of my Circular Singly Linked list.
But in that case it also returns me a NULL pointer and gives me out of bounds
message (implemented by me in code). I have included both my functions down
here
void remove_from_index(int index){
Node*temptr;
temptr = new Node;
int tempdata;
if (index==1)//means remove from first
{
temptr = firstptr;
tempdata= temptr->data;
firstptr = firstptr->nextptr;
lastptr->nextptr=firstptr;
delete(temptr);
} else if(index==size_of_list()) //means last node
{
temptr = pointer_to_node(index);
index--; //get pointer of 2nd last position
lastptr = pointer_to_node(index);//setting 2nd last as last postion
temptr->nextptr=NULL;
temptr=NULL;
lastptr->nextptr=firstptr;
delete (temptr);
} else // any position of node
{
temptr = pointer_to_node(index);
tempdata = temptr->data;
index--; // to get address of back
Node* temp2ptr;
temp2ptr = new Node;
temp2ptr = pointer_to_node(index);
index = index+2;
Node* temp3ptr;
temp3ptr = new Node;
temp3ptr = pointer_to_node(index);
temp2ptr->nextptr = temp3ptr;
temptr->nextptr=NULL;
delete (temptr);
}
}
Node* pointer_to_node(int index){
Node*temptr;
temptr = new Node;
temptr = firstptr;
Node*temptr2;
temptr2 = new Node;
temptr2 = NULL;
int count = 1;
while (temptr!=temptr2){
if (count==index)
{
return temptr;
}
count++;
temptr2=firstptr;
temptr=temptr->nextptr;
}
if (index>size_of_list())
{
temptr=NULL;
cout<< "Can't You think in bounds. Take your NULL Pointer ";
return temptr;
delete temptr;
delete temptr2;
}
}

You have several memory leaks:
temptr->nextptr=NULL;
temptr=NULL; // BAD!! BAD!! Remove it otherwise you will not actually free
lastptr->nextptr=firstptr;
delete (temptr);
And here too (actually you have this in four places of the code):
Node* temp2ptr;
temp2ptr = new Node; // BADD!! Why do you allocate if you are going to reassign?
temp2ptr = pointer_to_node(index);
Remove the bads and you will avoid the memory leaks.
Still, this is not going to fix your problem.
Also you have operations after return here:
return temptr;
delete temptr;
delete temptr2;
These are never going to be executed.
EDIT Your pointer_to_node function is too complex please change it with
Node* pointer_to_node(int index) {
Node* tempPtr = firstptr;
for (int i = 0; i < index; i++) {
tempPtr = tempPtr->nextptr;
}
return tempPtr;
}
And see if this will fix your problem. More lines of code very rarely means better programming skills, do not artificially try to increase their count.

I think another possible issue here, aside from all the memory leaks and style issues which are already well documented, is that your code does not seem to handle the case of there only being one thing in the list.
If that happens, it will delete that node, but leave firstptr and lastptr pointing at random memory.
If your size_of_list() function is just counting nodes in the list, it will probably still think there are non-zero nodes remaining, and you might then attempt to remove or otherwise access another node.

Related

Why is the delete temp crashing even though the function is defined with new

I am making a modified double ended Linked List, but the head and the tail point to each other. In the insertBeforeCurrent and the insertAfterCurrent I defined the objects with new and put them into the Linked List. But when I go to use delete, the program just crashes. I have done some tests, and insertBeforeCurrent and insertAfterCurrent works, and I am able to through the Linked List and print every single element with the getPrevious and getNext. I also printed it using only insertBeforeCurrent, insertAfterCurrent and I was also able to do the same with the mixture of the two. I was able to print it with 1,2,3,and 6 elements in the Linked List. The problem I have is the debugger, everything works until I hit the delete temp; at which point it will just say.
Can't find a source file at "/build/glibc-t7JzpG/glibc-2.30/signal/../sysdeps/unix/sysv/linux/raise.c"
Locate the file or edit the source lookup path to include its location.
I know you can only use the delete function for delete the data created by the new's dynamic memory allocation, but that doesn't seem to be the case since every element of the Linked List is created by new.
So the issue with application crashing is not the Node * x = new Node(); followed by x = y;. These don't show any warnings,the application runs, and 5 or 6 people have pointed them out. Thank you by the way. My issue is specifically is the delete temp;and why is it not being deleted. I have left the code for some context.
EDIT: I have removed the insertBeforeCurrent and insertAfterCurrent code since it is not needed.
bool CircularDoublyLinkedList::remove(int original_data)
{
Node search_data = search(original_data);
Node* temp = &search_data;
Node* current_next;
Node* current_previous;
if (temp != NULL)
{
if (temp == head)
{
current_previous = temp->getPrevious();
current_next = temp->getNext();
current_previous->setNext(current_next);
current_next->setPrevious(current_previous);
head = current_next;
temp->setNext(NULL);
temp->setPrevious(NULL);
delete temp;
current = current_next;
cout << "Delete successful." << endl;
}
else if (temp == tail)
{
current_previous = temp->getPrevious();
current_next = temp->getNext();
current_next->setPrevious(current_previous);
current_previous->setNext(current_next);
tail = current_next;
temp->setNext(NULL);
temp->setPrevious(NULL);
delete temp;
current = current_next;
cout << "Delete successful." << endl;
}
else
{
current_previous = temp->getPrevious();
current_next = temp->getNext();
current_previous->setNext(current_next);
current_next->setPrevious(current_previous);
temp->setNext(NULL);
temp->setPrevious(NULL);
delete temp;
}
return true;
}
return false;
}
I know you can only use the delete function for delete the data created by the new's dynamic memory allocation,
So far so good.
but that doesn't seem to be the case since every element of the Linked List is created by new.
This is not relevant, since the temp in CircularDoublyLinkedList::remove() never points to an element of the linked list. You assign to temp the address of a local variable (search_data) and never change that. Local variables are not created by new, so (as you noted earlier), you cannot delete &search_data.
(You might have noticed this yourself had you used a debugger to step through your code while trying to delete the first element of the list. In your current code, temp == head will never be true, even though that is the branch for deleting the first element. Similarly, temp == tail will never be true, and temp != NULL will never be false.)
At a guess, your search() function should probably return a pointer to a node in the list instead of returning the node, at which point you'll no longer need the (poorly-named) temp variable.

Linked list issue with overwriting variables

I am trying to code a linked list in C++, but I am running into a problem. When I insert only one item, it works, but when I insert more than one, it goes into an infinite loop. Here is the code:
#include "linkedList.hpp"
#include <iostream>
linkedList::node::node(int value)
{
internalValue = value;
next = nullptr;
previous = nullptr;
};
linkedList::linkedList()
: header{node(-2)}, trailer{node(-2)}
{
trailer.previous = &header;
header.next = &trailer;
size = 0;
}
int linkedList::getLength()
{
return size;
}
void linkedList::appendElement(int value)
{
node newNode = node(value);
newNode.next = &trailer;
newNode.previous = trailer.previous;
(trailer.previous)->next = &newNode;
trailer.previous = &newNode;
size = size + 1;
}
void linkedList::print()
{
node * current = header.next;
while (current -> next != nullptr)
{
std::cout << current -> internalValue << "->" << "\n";
current = current->next;
}
std::cout << "v";
}
After trying to debug it, I found that the issue is with the construction of a node. So the first time I try to insert 5, the program creates a node called new node, which is then appended perfectly fine.
What happens next is when a second number is to be appended, lets say 6, the program doesn't really create a new node object. Rather the variable name "newNode" still refers to the node with the value 5 stored in it and it replaces it with a node with the value of 6.
This understandably then creates an infinite loop since it essentially makes the array circular. I don't know how to fix this. Can someone point me in the right direction?
PS: sorry if this is extremely simple, I am very new to C++ (this is only my second day of coding)
In linkedList::appendElement(int value) you create a new node on the stack ( or 'automatic storage' ), which means the node will be destroyed when the function returns.
Instead, create the node on the heap ( or 'dynamic storage' ) using the new operator so it is not destroyed when the function returns.
node* newNode = new node(value);
You will also have to remember to destroy nodes yourself when the list is destroyed or truncated, and most C++ developers soon find it better to use smart pointers for that.

Deleting elements from doubly bounded pointer list

I am working on a project where I create a double bounded pointer list, delete several elements, and still be able to read off the list. I have a double bounded pointer list, but am having trouble deleting elements and keeping the list double bounded. This then causes issues when trying to print the list.
Below is the IF statement I've placed in a while loop to help delete unwanted elements. I keep getting a segmentation fault (core dumped).
if ((black2 != black)||(white2 != white)) {
dump = help;
help = help ->next;
dump -> before = temp;
temp -> next = help;
help ->before = temp;
delete dump;
}//if
else { temp = help;
help = help->next;
help ->before = temp; }//else
To maintain properly the doubly linked list you should do something like :
void remove(X *elt) {
X* before = elt->before;
X* after = elt->next;
if (before != NULL) { // assuming first element points to NULL
before->next = after;
}
else {
first = after; // assuming first is a pointer to first element of list
}
if (after != NULL) { // assuming last element points to NULL
after->before = before;
}
else {
last = before; // assuming last is a pointer to last element
}
delete elt;
}
That way, you ensure that elements around current correctly point to each other dealing with special cases of removing first or last element.
But you already have a std::list template in Standard Template Library
One logical issue in your code is the line dump->before = temp.
What this does is that it sets the previous node pointer of dump to temp, as opposed to defining temp as the previous node.
The correct line should read temp = dump->before
PS: Your code is correct assuming that the node you are deleting isn't the first or last node (and you haven't padded with dummy nodes). You should introduce checks for these cases if required.

why i cannot delete my node with reference

void deleteElement(LinkedListElement<char> *&pending)
{
if (pending->Next) {
char value = pending->Next->Data;
pending->Data = value;
LinkedListElement<char> *temp = pending->Next;
pending->Next = pending->Next->Next;
delete temp;
}else{
delete pending;
pending = NULL;
}
}
LinkedListElement<char> *l1 = new LinkedListElement<char>('a');
LinkedListElement<char> *l2 = new LinkedListElement<char>('b');
LinkedListElement<char> *l3 = new LinkedListElement<char>('a');
LinkedListElement<char> *l4 = new LinkedListElement<char>('c');
l1->setNext(l2); l2->setNext(l3); l3->setNext(l4);
printLinkedList(l1);
deleteElement(l4);
printLinkedList(l1);
Simple tricky delete node in C++ what i want to ask is in the else statement, if the linked list is end , so i can just delete the end itself.
but the two print function, will always print abac, and second way abac.
because i just pass the parameter with reference, (&), i think if i want to delete l4
i do not need to change l3->Next, becasue i can change l4 to NULL, and l3->Next will be NULL.
i try to use
delete pending; pending=NULL;
why it is does not work, two print function always print abac
You delete l4, but you never change l3, and it points to l4s memory (now deleted) which still contains the data ('c')
You need to
l3->setNext(NULL);
to remove the element from the list (and you must still delete it of course)
To use the deleteElement function, you would need to change it to iterate through the list (Pseudo code):
void deleteElement( Element head , Element toBeDeleted)
{
//are we deleting head (the first element of the list?)
//yes then head should be nulled, and delete as normal
current = head ; ancestor = head;
//scan through list (current becomes current->next until no more)
//until we find toBeDeleted
//maintain ancestor as we go
//if found set ancestor->next to current->next
//delete toBeDeleted
}

C++ assigning a new address to *next in a data structure

there's something I can't get my head round...
Basically I'm given the following data structure:
struct node_ll {
int payload;
node_ll *next; //pointer to next node
};
Which is essentially a stack of numbers.
I need to create a method with the following prototype:
int tail_return(node_ll **list)
where **list is the memory address of the above data structure. My implementation is as follows:
int tail_return(node_ll **list) {
node_ll *temp;
temp = *list;
node_ll *prev_temp;
prev_temp = *list;
bool firstPass = true;
while(temp){
if(firstPass == true){
temp = temp->next;
firstPass = false;
} else {
temp = temp->next;
prev_temp = prev_temp->next;
}
}
int toReturn = prev_temp->payload;
prev_temp->payload = 0;
(**list).next = prev_temp;
delete temp;
delete prev_temp;
return toReturn;
}
However I get the following output from test runs:
List a after head insertion of 2,4,6,8,10 elements:
{10,8,6,4,2}
now removing the last element
DELETED: 2
{10,0} where it's supposed to be: {10,8,6,4}
What am I doing wrong? Apparently the method finds the right value to delete - 2. But why when I try to print it after deletion I end up with 10 and 0?
(**list).next = prev_temp;
should be
prev_temp->next = 0 ;
when you do (**list).next = prev_temp; you are manipulating the parameter which was passed to your method and not the last node in the linked list.
I am assuming that tail_return is supposed to take a linked list of node_ll 's and delete the tail element?
Yes per #Aditya , looks like the
(**list).next = prev_temp;
line is causing a problem. The reason is that you are reassigning list to point to the second to last element (prev_temp).
Deleting the last element is correctly done by
delete temp;
And also remove the line
delete prev_temp;
since that removes the second to last element too, which you want to keep.
Plus you are currently returning the second to last element. So change
int toReturn = prev_temp->payload;
to
int toReturn = temp->payload;
(**list).next = prev_temp;
is too complicated. If you write it like this
(*list)->next = prev_temp;
it now becomes clear(er) that you change the first element in the list.
This is just a small recommendation for writing clearer code. See the other answers for the solutions to your problem(s).