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
}
Related
I have developed a function to remove all nodes from linked list. All nodes are successfully deleted except the last one. Please help me why last node is not being deleted? Following is my code:
void StudentLinkList::removeAll() {
StudentData *traversePointer = this->head;
while (this->head->getNext() != nullptr) {
this->head = this->head->getNext();
delete traversePointer;
traversePointer = this->head;
}
delete this->head;
}
So close
void StudentLinkList::removeAll() {
StudentData *traversePointer;
// Continue while there are any elements on the list
// Extra parens to indicate that we want the result of the
// assignment as boolean. No need to compare to nullptr.
while ( (traversePointer = this->head) ) {
// First preserve the rest of the list
this->head = this->head->getNext();
// only then can we delete this node
delete traversePointer;
}
// list is now empty
}
You're deleting this->head, but you should set this->head to nullptr as well. While you're freeing the memory the node is using, the data stored in the node's old location usually isn't immediately overwritten, which is why it looks like the last node is not deleted.
EDIT: downvote is duly noted, could someone clarify what I got wrong?
Also, I agree with the above comment - you should also check if this->head is null before the loop.
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.
I have a linked list contains 3 nodes like the image shown:
There is a head pointer and temp1 pointer point to the front of the list, and tail point points at the end of the list.
I want to remove all the nodes, and change it back to its original initial form ( tail = NULL, head = first_node , but the first node doesn't have any value in the data and next field).
Because I want to start putting up some new values in it. To remove all those data, is this code going to remove nodes inside this linked list and left with the first node with no values in data and next field?
This code is in C++:
while(temp1!=tail)
{
temp1 = temp1->next;
if(temp1->next == tail)
{
tail=temp1;
temp1 = temp1->next;
free(temp1);
}
}
But then, does this mean only the last node will be deleted? are there any way to delete all the nodes except the first one?
To delete all nodes except the first node, you can try below code.
temp1 = head->next;
while(temp1!=NULL) // as I am considering tail->next = NULL
{
head->next = temp1->next;
temp1->next = NULL;
free(temp1);
temp1 = head->next;
}
This will delete all nodes except first one. But the data with the first node will remain as it is.
Disclaimer: I assume it's only for learning purposes and in real-world scenario you would use std::list<> or similar container.
For single-linked list, you can just drop all this burden an let the stdlib manage the pointers:
class Node {
std::unique_ptr<Node> next;
};
You can safely use .reset() method to make operations on the list:
Given current_ptr, the pointer that was managed by *this, performs the following actions, in this order:
Saves a copy of the current pointer old_ptr = current_ptr
Overwrites the current pointer with the argument current_ptr = ptr
If the old pointer was non-empty, deletes the previously managed object if(old_ptr != nullptr) get_deleter()(old_ptr).
From http://en.cppreference.com/w/cpp/memory/unique_ptr/reset.
And that's pretty much what you would do when deleting. I believe you can also use unique_ptr::swap(), to easily manipulate your nodes.
Instead of free, C++ uses delete function.
Check the link to have deep knowledge about all kind of operations(including recursive or iterative delete) on linked lists.
temp1 = head->next;
while(temp1!=NULL) // as I am considering tail->next = NULL
{
head->next = temp1->next;
temp1->next = NULL;
free(temp1);
temp1 = head->next;
}
The logic for this would be more correct if it is this way.
After the statement
free(temp1);
Add the condition
if (head -> next != NULL)
temp1 = head->next;
Since after deleting the last node there is no point in reassigning the address of head pointer to temp1.
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).
I have the following array structure (linked list):
struct str_pair
{
char ip [50] ;
char uri [50] ;
str_pair *next ;
} ;
str_pair *item;
I know to create a new item, I need to use
item = new str_pair;
However, I need to be able to loop through the array and delete a particular item. I have the looping part sorted. But how do I delete an item from an array of structures?
What you've shown is not an array of struct, but a linked list of struct containing arrays (of type char).
An array of struct would look like this:
str_pair array_of_structs[10];
// or:
str_pair* dynamically_allocated_array_of_structs = new str_pair[10];
If you actually have something like this, you don't need to delete single items from an array. Let's say you've initialized your array as follows:
str_pair* array_of_structs = new str_pair[10];
Then you delete the whole array (including all of its items) using:
delete[] array_of_structs;
Again, you can't delete single items in an array allocated with new[]; you perform a delete[] on the whole array.
If, on the other hand, you intended to say "linked list of struct", then you'd generally delete an item similarly to the following:
str_pair* previous_item = ...;
str_pair* item_to_delete = previous_item->next;
if (item_to_delete != 0)
{
previous_item->next = item_to_delete->next; // make the list "skip" one item
delete item_to_delete; // and delete the skipped item
}
Or, in English: Find the item (A) preceding the item which you want to delete (B), then adjust A's "next" pointer so that B will be skipped in the list, then delete B.
You need to be careful with special cases, i.e. when the item to be removed from the list is the first item or the last one. The above code is not sufficient when you want to delete the first item in the list, because there will be no previous_item. In this case, you'd need to change the pointer to the list's first element to the second element.
Your code:
void deleteitem(char *uri)
{
str_pair *itemtodelete;
curr = head;
while (curr->next != NULL) {
if ((strcmp(curr->uri, uri)) == 0) {
itemtodelete = curr;
curr = itemtodelete->next;
delete itemtodelete;
curr = head;
return;
}
curr = curr->next;
}
}
Some things are wrong here:
If head is null, the test curr->next != NULL will cause a segfault. (You must never dereference a null pointer!)
Your code for removing an item from the list is completely incorrect. Worst of all, you delete a node without changing the previous item's next pointer. The previous item will thus reference an item that's no longer there.
A detail: curr = head; before the return statement doesn't do anything useful at all.
Suggested code:
Do it in two steps: One function to find the node to be deleted via its attached uri, and one function to remove the node. You could separate it even better than the code below does, but it should be a starting point:
str_pair* finditemwithuri(char* uri)
{
str_pair* current = head;
while (current)
{
if (strcmp(current->uri, uri) == 0) return current;
current = current->next;
}
return 0;
}
void deleteitem(char* uri)
{
// find linked list node with that uri; abort if uri not in list
str_pair* itemtodelete = finditemwithuri(uri);
if (!itemtodelete) return;
// special case: node to be deleted is the list's head
if (itemtodelete == head)
{
head = itemtodelete->next;
delete itemtodelete;
return;
}
// else, iterate over list nodes
// up to the one preceding the node to be deleted
str_pair* current = head;
while (current)
{
if (itemtodelete == current->next)
{
current->next = itemtodelete->next;
delete itemtodelete;
return;
}
current = current->next;
}
}
Just use std::list. There's no reason to manually write such a construct.
http://msdn.microsoft.com/en-us/library/802d66bt(VS.80).aspx
std::list offers remove.
You can delete it using the ordinary delete keyword, but that will not shift all other members of the array. If you want this kind of behaviour take a look at std::vector or something like that.
It is maybe off topic, but why dont you use the std::list library ?
As others have pointed out, this is a Linked List, not an array. To answer your question for linked lists:
To insert an item:
str_pair* p = // iterate over the linked list to your insertion point
str_pair* item = new str_pair;
item->next = p->next;
p->next = item;
That inserts a new str_pair after p.
To remove an item:
str_pair* p = // iterate to just before your deletion point
str_pair* item = p->next;
p->next = p->next->next;
delete item;
This will remove the element after p
To do this with your code:
void deleteitem(char *uri)
{
str_pair *previous = NULL;
curr = head;
while (curr != NULL) {
if ((strcmp(curr->uri, uri)) == 0) {
// modify the previous element to skip over our deleted one
if (previous)
previous->next = curr->next;
else
head = curr->next;
// safely delete the element, now that no one points to it
delete curr;
curr = head;
return;
}
// always remember our previous element, so we can fix its 'next' pointer
previous = curr;
curr = curr->next;
}
}
You need a better add method too:
void additem(char *uri, char *ip)
{
curr = head;
// traverse the list until we're at the last item
while (curr->next != NULL) {
curr = curr->next;
}
// attach a new element to the list
curr->next = new str_pair;
// go to that new element
curr = curr->next;
// set the values of the new element
strcpy(curr->ip, ip);
strcpy(curr->uri, uri);
curr->next = NULL;
curr = head;
}