I am currently writing some code which will delete the last node from a linked list, i have the code below; but it is deleting the previous node to the last node; not the last node itself.
Any help will be appreciated:
if(p!=NULL) {
if( p->next!=NULL) {
Student *todel = p->next;
p->next= p->next->next;
delete todel; //free(todel);
} else {
delete p; //If n = 0 && its the last element, delete it
}
}
EDIT:
I have now edited this code to look like the below......it is not working; is it because I am pointing to a NULL vaue, then deleting that null value?
if(p!=NULL) {
if( p->next==NULL) {
delete p;
}
}
Check this one.
if(p!=NULL) {
if ( p->next!=NULL) {
while (1) {
Student *todel = p->next;
if (todel->next == NULL) {
// todel is indeed the last node, delete it
delete todel;
p->next = NULL;
break; // break from infinite while loop that was looking for last node
}
else {
// todel is not last node, go further
p = todel->next;
}
}
} else {
delete p; //If n = 0 && its the last element, delete it
}
}
Try the following instead inside the loop you are using to walk the linked list.
if(p->next!=NULL) {
if (p->next->next == NULL) {// Found the second-to-last-node
delete p->next; // Kill the last node
p->next = NULL; // Make the current node the last node.
}
}
Try this, I didn't test it.
void delete_lastnode(Node* head)
{
Node *p = head;
if (p == NULL) // NULL list
return;
if (p->next == NULL) // Single node list
{
delete head;
head = NULL;
return;
}
while(p->next->next != NULL) // Find the second-last node
{
p = p->next;
}
Node* temp = p->next;
p->next = NULL;
delete temp;
temp = NULL;
}
Related
I have stressed my head out the last few days to figure out how to get this remove() function to work. I'm still a student and data structure is no joke.
I really need help on how to get this function to remove a specific number on the list from user input. Doesn't matter what I try, it still could not work right.
For example, the list is: [1, 2, 3]
I want to delete number 2 on the list. I want the remove() function to traverse thur the list, if it found number 2, then delete number 2.
class SortedNumberList {
public:
Node* head;
Node* tail;
SortedNumberList() {
head = nullptr;
tail = nullptr;
}
void Insert(double number) {
Node* newNode = new Node(number);
if (head == nullptr) {
head = newNode;
tail = newNode;
}
else {
tail->SetNext(newNode);
tail = newNode;
}
}
// Removes the node with the specified number value from the list. Returns
// true if the node is found and removed, false otherwise.
bool Remove(double number) {
Node* temp = head;
if (temp == nullptr) {
return false;
}
if (head->GetData() == number) {
head = head->GetNext();
return true;
}
else{
while (temp != nullptr) {
Node* curNode = temp;
Node* preNode = nullptr;
preNode = curNode->GetPrevious();
temp = temp->GetNext();
if (curNode->GetData() == number) {
preNode = curNode->GetNext();
return true;
}
delete curNode;
}
}
delete temp;
}
};
class Node {
protected:
double data;
Node* next;
Node* previous;
public:
Node(double initialData) {
data = initialData;
next = nullptr;
previous = nullptr;
}
Node(double initialData, Node* nextNode, Node* previousNode) {
data = initialData;
next = nextNode;
previous = previousNode;
}
Edit: I'm able to solve my own issue, thank you everyone.
bool Remove(double number) {
// Your code here (remove placeholder line below)
Node* temp = head; //Make a temporary node point to head.
if (temp == nullptr || head == nullptr) { //if user don't provide input, return false.
return false;
}
if (head->GetData() == number) { //If number need to delete is at head.
head = head->GetNext();
return true;
}
else {
while (temp != nullptr) { //Travese temp node throught out a list.
Node* curNode = temp->GetNext(); //Make a current node point at temp next.
Node* preNode = temp;
Node* sucNode = curNode->GetNext();
if(curNode->GetData() == number) { //Delete a node if number is found on the list
if (curNode->GetNext() == nullptr) { //Delete at tail.
preNode->SetNext(nullptr);
tail = preNode;
delete curNode;
return true;
}
if (curNode->GetNext() != nullptr) {
preNode->SetNext(sucNode);
sucNode->SetPrevious(preNode);
delete curNode;
return true;
}
}
temp = temp->GetNext();
}
}
return false;
}
};
You should make Node a friend class of SortedNumberList or define former inside the later class which simplifies the code somewhat. It's personal preference but it leads to less unnecessary boilerplate code (getters and setters).
In a double linked list you do not need to keep track of the last as you do need on single linked lists because you have both pointers available.
The quest is just a matter of iterating to find the value, taking care to cut it early when we pass the mark since it is a sorted list.
Then delete the object and update the link pointers.
bool Remove(double number) {
// Loop through the entire list
Node* temp = head;
while ( temp != nullptr) {
// There is no point looking forward if the list is sorted
if (temp->data > number ) return false;
// Compare to find
if (temp->data == number) {
// Get the pointers so we can delete the object
Node* prev = temp->previous;
Node* next = temp->next;
// Delete object
delete temp;
// Update previous pointers
if ( prev==nullptr ) {
head = next;
} else {
prev->next = next;
}
// Update next pointers
if ( next==nullptr ) {
tail = prev;
} else {
next->previous = prev;
}
// Indicate success
return true;
}
}
// We iterated to the end and did not find it
return false;
}
I have the two functions below and I can get the removeAfter function to work correctly but then when trying to implement the removeBefore function the linked list is not changed at all. Am I missing something? I have made necessary changes, but am still getting the same result: removeBefore does not output any changes to the list.
// remove the node after the node p
void DoublyLinkedList::removeAfter(DListNode &p){
if (isEmpty()){
throw EmptyDLinkedListException("Empty Doubly Linked List");
}
DListNode *to_delete = &p;
to_delete = to_delete->next;
if (to_delete != NULL){
if(to_delete->next != NULL){
to_delete->prev->next = to_delete->next;
}
if(to_delete->prev != NULL){
to_delete->next->prev = &p;
}
if (to_delete == &trailer) {
trailer = *to_delete->prev;
}
}
if (to_delete == NULL){
throw EmptyDLinkedListException("Cannot delete a null pointer");
}
delete to_delete;
}
// remove the node before the node p
void DoublyLinkedList::removeBefore(DListNode &p){
/* Complete this function */
if (isEmpty()){
throw EmptyDLinkedListException("Empty Doubly Linked List");
}
DListNode *to_delete = &p;
to_delete = to_delete->prev;
if (to_delete != NULL){
if (to_delete->next != NULL) {
to_delete->next->prev = to_delete->prev;
}
if (to_delete->prev != NULL) {
to_delete->prev->next = to_delete->next;
}
if (to_delete == &header) {
header = *to_delete->next;
}
}
if (to_delete == NULL){
throw EmptyDLinkedListException("Cannot delete a null pointer");
}
delete to_delete;
}
There are errors in your code.
First off, a linked list is a list of pointers, so it is not customary to pass around nodes by reference. You really should be passing them by pointer instead.
removeAfter() does not account for the possibility that p.next might be NULL upon input (when p is the last node in the list). And it is not updating to_delete's siblings correctly before then deleting to_delete itself. It should look like this instead:
void DoublyLinkedList::removeAfter(DListNode *p)
{
DListNode *to_delete = p->next; //Get to the node after p that is to be deleted
if (to_delete != NULL)
{
if (to_delete->next != NULL) {
to_delete->next->prev = to_delete->prev;
}
if (to_delete->prev != NULL) {
to_delete->prev->next = to_delete->next;
}
// update the tail pointer if to_delete is the tail node...
if (trailer == to_delete) {
trailer = to_delete->prev;
}
delete to_delete;
}
}
removeBefore() is making similar mistakes. It does not account for the possibility that p.prev might be NULL upon input (when p is the first node in the list) or even that it might be the head node of the list. It should look like this instead:
void DoublyLinkedList::removeBefore(DListNode *p)
{
DListNode *to_delete = p->prev; //Get to the node before p that is to be deleted
if (to_delete != NULL)
{
if (to_delete->next != NULL) {
to_delete->next->prev = to_delete->prev;
}
if (to_delete->prev != NULL) {
to_delete->prev->next = to_delete->next;
// update the head pointer if to_delete is the head node...
if (header == to_delete) {
header = to_delete->next;
}
delete to_delete;
}
}
That being said, the logic would be better implemented by centralizing it, eg:
void DoublyLinkedList::remove(DListNode *p)
{
if (p = NULL) return;
if (p->next != NULL) {
p->next->prev = p->prev;
}
if (p->prev != NULL) {
p->prev->next = p->next;
}
if (header == p) {
header = p->next;
}
if (trailer == p) {
trailer = p->prev;
}
delete p;
}
void DoublyLinkedList::removeAfter(DListNode *p)
{
remove(p->next);
}
void DoublyLinkedList::removeBefore(DListNode *p)
{
remove(p->prev);
}
That being said, once you understand how double-linked lists work, you should throw away all of this code and just use the STL std::list class instead, which is a standard double-linked list implementation.
What I am trying to do is check if node after value is specific number and if is, then delete previoues node.
Something like:
1,2,3,4,5,4
if next node number is 4 then delete this node.
1,2,3,4,5,4 -> 1,2,4,4
node* temp = head;
while (head != NULL) {
if (head->next->number == 4) {
delete temp;
}
head = head->next;
}
Struggling at this moment as compiler crashes.
You delete the head before you advance it:
node *temp = NULL;
while (head->next != NULL) {
if (head->next->number == 4) {
temp = head;
}
if ( temp == NULL ){
head = head->next;
}
else{
head = head->next->next;
delete temp;
temp= NULL:
}
}
I am trying to delete the last Node of a linked list,
I have the first element of the list. But the function does not work I would be happy if you could help me
Code -
void deleteNode(Node* firstNode)
{
Node* currNode = firstNode;
while (currNode->next != NULL)
{
currNode = currNode->next;
}
delete currNode->next;
currNode->next = NULL;
}
You are deleting the one after the last node, which should be NULL anyways.
void deleteNode(Node* firstNode)
{
//first check if firstNode is NULL or last node.
if(firstNode == NULL)
return;
if(firstNode->next == NULL)
{
delete firstNode;
firstNode = NULL;
return;
}
Node* currNode = firstNode;
while (currNode->next && currNode->next->next != NULL)
{
currNode = currNode->next;
}
delete currNode->next;
currNode->next = NULL;
}
You need to consider a few things:
Any operation that could potentially affect the head pointer must provide a mechanism for returning the updated head pointer (an in/out param i.e. pointer to pointer or reference-of-pointer, or by function return result; I prefer the former).
Any pointer holding the address of the last node in the list, be it the head pointer or any other, must be set to NULL.
That said,
Pointer To Pointer
void deleteLastNode(Node** firstNode)
{
while (*firstNode && (*firstNode)->next)
firstNode = &(*firstNode)->next;
free(*firstNode); /**/
*firstNode = NULL; /**/
}
Note if the pointer passed in by-address is already NULL, both lines above marked with /**/ need not be executed, but are harmless none-the-less, as free()-ing NULL is supported per the standard as a no-op.
Called by passing the address of the head pointer, the content of which must be NULL if the list is empty.
Node *head = NULL;
//... code to populate the list.
deleteLastNode(&head);
Reference of Pointer
With C++, you can also pass the head pointer by reference, for example:
void deleteLastNode(Node*& head)
{
Node **firstNode = &head;
while (*firstNode && (*firstNode)->next)
firstNode = &(*firstNode)->next;
free(*firstNode); /**/
*firstNode = NULL; /**/
}
Invoked as:
Node *head = NULL;
//... code to populate the list.
deleteLastNode(head);
Which mechanism you choose is up to you.
You are deleting one after the final node.
delete currNode;
Try this:
void deleteNode(Node *firstNode)
{
Node* currNode = firstNode;
Node* nextNode = firstNode->next;
while(nextNode != NULL)
{
currNode = nextNode;
nextNode = nextNode->next;
}
delete currNode;
}
The problem with your code is, at the last instance curNode points to the last node of the list. When you delete the curNode, you will no longer be left with node, ie, the data and next part. So you now you cannot access next part of curNode. This code will lead to runtime error:
currNode->next = NULL;
Instead try this:
If the list contains only one element, then firstNode points to NULL and the only node is deleted. If there are more than two items in your list, your have to iterate to the last second element, set its next value to NULL, and delete the last node with the help of a temp pointer.
void pop_back(struct node** firstNode)
{
struct node* p = *firstNode;
if(p == NULL)
cout << "List empty." << endl;
else if(p->next == NULL){
cout << "Element " << p-> data << " deleted." << endl;
delete *firstNode;
*firstNode = NULL;
}
else
{
while(p->next->next != NULL){
p= p->next;
}
struct node* temp = p-> next;
p->next = NULL;
cout << "Element " << temp->data << " deleted." << endl;
delete temp;
}
}
void delBottom()
{
clrscr();
Node *nb=H; //current
Node *nn=(H->getNext()); //next
if(NULL==H)
{
cout<<"List Empty";
}
else if(H==T)
{
delete H; //H-Head
H=T=NULL;
}
else
{
while(NULL!=(nn->getNext()))
{
nb=nn;
nn=nn->getNext();
}
delete nn;
nb->setNext(NULL);
T=nb; //T-Tail
}
}
actually, you should write like this:
void deleteNode(Node* firstNode)
{
Node* currNode = firstNode;
while (currNode->next != NULL)
{
currNode = currNode->next;
}
***delete currNode;
currNode = NULL;***
}
cause, currNode is the last node.
I am trying to delete all specific key element in my linked list in one function .
that is if linked list has 1 2 2 3 4 4 5 5 8 2 6 32 4 6 7 7 then if I pass the function 2 that function delete all the 2's in linked list
my linked list is here
class float_list
{
struct node
{
double data;
struct node *next;
};
node *head;
public:
float_list(void)
{
head = nullptr;
};
void appendNode(double);
void print_list();
void deleteNode(double);
};
now my deleteNode(double is here)
void float_list::deleteNode(double num)
{
node *nextptr, *previousptr = nullptr;
nextptr=head;
if(!head->data){return;}
if(head->data==num)
{
nextptr= head->next;
delete head;
head = nextptr;
}
else
while(nextptr)
{
previousptr= nextptr;
if(nextptr->data==num)
{
previousptr->next = nextptr->next;
delete nextptr;
cout<<"I Found the --> "<<num<<" is going to be deleted"<<endl;
nextptr = previousptr;
//nextptr = nextptr->next;
}
nextptr = nextptr->next;
}
delete nextptr;
delete previousptr;
}
I tried in all different ways but always get accesss violation error . Please give me conceptual and code hints if possible . thanks
the code is in win32 Vs2010 app
What happens after the while loop end. Well, nextptr == NULL. delete NULL == problem.
Try this:
node *previous = nullptr, *current = head, *temp;
while(current){
temp = current->next;
if(abs(current->data - num) < MARGIN_OF_ERROR){
if (previous){
previous->next = current->next;
} else {
head = current->next;
}
delete current;
} else{
previous = current;
}
current = temp;
}
something like this (pseudo-code)
public void removeData( double data )
{
if ( this.node == null ){ return; }
if ( this.node->data == data ){
this.node = this.node.node;
}
this.node.removeData( data );
}
Two issues I can trace:
You should never use operator== to check equality of two floating
point numbers, there is an issue with floating point arithmetic -
they are not exact, and result might not be as you expect [not a solution to your problem but definetly an issue]
Your previousptr and nextptr are the same thing [they are both pointing at the same address!]. You should modify previousptr before the current iteration. [right before nextptr = nextptr->next;]. Because of it, when you delete nextptr and later set:
nextptr = previousptr;
nextptr = nextptr->next;
You are actually accessing the element you just deleted, which causes your illegal access.
Probably this can be done through recursion, but here is a moving pointer solution:
void removenumber(node **head, int value)
{
node * current;
node * prev;
node * tmp;
current = (*head);
if ( current == NULL) return;
prev = current;
current = current->next;
while( current!= NULL && current->next != NULL)
{
if ( current->data == value)
{ //remove current
tmp = current->next;
prev->next = current->next;
free(current);
current = tmp;
//previous is the same
continue;
}
current = current->next;
prev = prev->next;
}
// now current->next != NULL check it
if(current!=NULL) //what is current was deleted?
{
if(current->data == value )
{
prev->next = NULL;
free(current);
}
}
if ( (*head)->data == value) //remove head
{
tmp = (*head)->next;
free(*head);
*head = tmp;
}
}