deleting all specific keys found in linked list - c++

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;
}
}

Related

C++ Need help on Remove Node function

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;
}

How do you delete all the nodes on the right of a linked list when a value greater than 'x' is encountered?

I don't see solution to this specific question on stackoverflow. So I'm posting this.
My requirement is to delete all the nodes on the right of a linked list when a value greater than 'x' is encountered?
For Ex.
Sample Input:
Linked list has values: 5 1 2 6 and x = 5
Output: 5 1 2
Sample Input
Linked list has values: 7 1 2 6 and x = 6
Output: null (since 7 is greater than 6, it should delete all the nodes on the right)
Sample Input:
Linked list has values: 5 4 7 6 and x = 6
Output: 5 4
I came up with this solution, but I'm trying to find an optimal solution
//head is the root node, nodes greater that "value" should be deleted
Node Delete(Node head, int value) {
// Complete this method
Node cur = head;
Node prev = null;
if(cur == null)
return head;
if(cur != null && cur.data > value )
{
while(cur != null)
{
prev = cur;
cur = cur.next;
}
prev.next = cur;
head = prev;
return head;
}
else
{
while(cur != null && cur.data <= value)
{
prev = cur;
cur = cur.next;
}
if(cur != null && cur.data > value)
{
while(cur != null)
{
cur = cur.next;
}
prev.next = cur;
return head;
}
prev.next = null;
return head;
}
}
Here is a simple O(n) solution in Javascript-style pseudocode,
with several identifiers renamed for clarity.
function deleteGreater(head, value) {
if (head == null) return null;
if (head.data > value) {
deallocate(head); //discard the entire list
return null;
}
var current = head;
while (true) {
if (current.next == null) return head; //end of list
if (current.next.data > value) break;
current = current.next;
}
deallocate(current.next); //discard the rest of the list
current.next = null;
return head;
}
I trust you can convert it to any language you want.
For languages with garbage collection, you can remove the deallocate() calls.
For languages without garbage collection, override the object's deallocation method to make sure that it also deallocates the next property.
In language like Java which have garbage collection, it is as simple as to set the next of last element to null which in worst case will be of O(n) (which will happen when matched with last element)
Node deleteGreaterThan(Node head, int value){
if(head==null || head.data>value)return null;//if head is itself greater than value
Node temp = head;
while(temp.next != null && temp.next.data<=value){
temp= temp.next;
}
temp.next = null;
return head;
}
head = deleteGreaterThan(head, 5);
I guess in language like c, you might have to explicitly delete each element and free the memory, no experience with c, so can't say much, even in that case it will only be O(n)
Like #100rabh said, in a language without garage collection you need to free every single node you allocated. Here is an example in C of how to do that. Notice that calling Delete is still O(n) because we actually update the previous node's next pointer while freeing the current node.
#include <malloc.h>
#include <stdio.h>
struct _Node {
struct _Node *next;
int data;
};
typedef struct _Node Node;
Node* Build(int value)
{
int i;
Node *ptr, *head=NULL;
for (i=1; i<value; i++)
{
if(head==NULL)
{
head=malloc(sizeof(Node));
ptr=head;
}
else
{
ptr->next=malloc(sizeof(Node));
ptr=ptr->next;
}
ptr->data=i;
ptr->next=NULL;
printf("Build: node=%p {data=%d next=%p}\n", ptr, ptr->data, ptr->next);
}
return head;
}
void Print(Node *head)
{
Node *ptr=head;
while(ptr!=NULL)
{
printf("Print: node=%p {data=%d, next=%p}\n", ptr, ptr->data, ptr->next);
ptr=ptr->next;
}
}
/*
* We can't pass head or ptr->next directly
* Because then we can't update it's value when we free what it points to
* So we pass the pointer to head or ptr->next instead
* Here we actually update head or ptr->next to point to the next node until we are finished
*/
void Free(Node **ptr)
{
Node *temp;
if(ptr==NULL) return;
while(*ptr!=NULL)
{
temp=*ptr;
*ptr=(*ptr)->next;
printf("Free: node=%p {data=%d next=%p}\n",temp,temp->data,temp->next);
temp->data=-temp->data;
temp->next=NULL;
free(temp);
}
}
/*
* We can't pass head or ptr->next directly
* Because then we can't update it's value when we free what it points to
* So we pass the pointer to head or ptr->next instead
* Nothing gets updated in this function - Free does all the updating
*/
void Delete(Node **ptr, int value)
{
if(ptr==NULL) return;
while(*ptr!=NULL)
{
if((*ptr)->data>value)
{
printf("Delete: node=%p {data=%d node=%p}\n",*ptr,(*ptr)->data,(*ptr)->next);
Free(ptr);
return;
}
ptr=&(*ptr)->next;
}
}
int main(void)
{
Node *head=Build(10);
Print(head);
Delete(&head, 5);
Print(head);
Free(&head);
return 0;
}

add element after specifiec element in linked list and delete first element

I tried hard to solve this problem but only managed to partially solve it.
My problem in this method is that I need to add an element after another element:
Example: add 5 1
5 is an element in the linked list but I want to add 1 after 5.
Example: let linked list contains these elements : 2 3 7
I call method to add 1 after 3, add 3 1, so the result assume to be 2 3 1 7, but with my method the result is 2 1 3 7, which is my problem.
Second problem is that I can't deal with the first element:
Example: add 2 1
It acts as if the first element does not exist:
void addNodeAtPos(link *head, int pos,int addelement)
{
link prev=NULL;
link curr =*head;
link newNode = (link)malloc(sizeof(node));
newNode->data = addelement;
while(curr->next != NULL )
{
prev = curr;
curr = curr->next;
if(curr->data == pos)
{
newNode->next = curr;
prev->next = newNode;
break;
}
}
}
My problem here is that I can't remove the first element:
void deletenode(link *head,int s){
bool found = false;
node *curr = *head, *prev=NULL;
while(curr != NULL){
// match found, delete
if(curr->data == s){
found = true;
// found at top
if(prev == NULL){
link temp = *head;
curr->next= prev;
delete(temp);
// found in list - not top
}else{
prev->next = curr->next;
delete(curr);
} }
// not found, advance pointers
if(!found){
prev = curr;
curr = curr->next; }
// found, exit loop
else curr = NULL; }
}
Here's the solution to the first problem
if(curr->data == pos)
{
// tempNode = curr->next;
// improvement as suggested by #Rerito
newNode->next = curr->next;
curr->next = newNode;
break;
}
It appears you are using non-circular doubly linked lists. Thus, both ends of the list are marked with NULL. Now, it seems to me that you use C++ in a very C-esque fashion ... (NULL would'nt be used in C++, there is the nullptr keyword).
I will deal with your issues assuming you are using C instead of C++.
// Note that I pass a link **ptr, NOT a link *ptr ...
void addNodeAtPos(link **head, int pos, int addelement) {
// I am assuming head will be a valid pointer, if not, please add the appropriate checks.
link *newNode = NULL, *cur = *head;
if (NULL == (newNode = malloc(sizeof(link)))
return;
newNode->data = addelement;
while (cur != NULL) {
if (cur->data == pos || NULL == cur->next) {
newNode->next = cur->next;
newNode->prev = cur; // remove this line if there is no prev pointer.
cur->next = newNode;
if (NULL != newNode->next) { // remove this if clause if there is no prev pointer
newNode->next->prev = newNode;
}
break;
}
cur = cur->next;
}
}
You did not specify what you should do if the "position" is not found, I assumed that you just add the element at the end of the list in that case.
Now, considering your issue removing the first element :
void deleteNode(link **head, int el)
{
// I assume you wont pass a `NULL` ptr as #head
link *cur = *head, *prev = NULL;
while (cur != NULL) {
if (cur->data == el) {
next = cur->next;
prev = cur->prev;
free(cur);
if (NULL != next)
next->prev = prev;
if (NULL != prev)
prev->next = next;
else
*head = next;
break;
}
cur = cur->next;
}
}
Why do you need to pass a link **head instead of a link *head ? Because when you are removing the head of the list, you must make sure it won't be accessed anymore and thus you need to update the head pointer you use elsewhere. This is what is made in the *head = next; statement in the above function.
If you are using singly linked list (only a pointer to the next element, not the previous), the solution becomes the following :
void deleteNode(link **head, int el)
{
// I assume you wont pass a `NULL` ptr as #head
link *cur = *head, *prev = NULL, *next = NULL;
while (cur != NULL) {
if (cur->data == el) {
if (NULL != prev)
prev->next = cur->next;
else
*head = cur->next;
free(cur);
break;
}
prev = cur;
cur = cur->next;
}
}

C++ Pointers, Linked List Confusion

I am trying to build a linked list in C++. My understanding is that the code I have created should create a node and then progressively link 4 more onto the end. Unfortunately, while I would expect to see the cout results as "12 123 1234 12345" I'm seeing "12 12 12 12" and in my main I am unable to traverse the list - it just crashes.
I have the following code:
struct listNode {
int val;
listNode* next;
};
int nodeCount = 0;
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
int main()
{
listNode* first = addToEnd(NULL);
addToEnd(first);
addToEnd(first);
addToEnd(first);
addToEnd(first);
cout<<"Third: "<<first->next->next->val;
}
Any help is appreciated, as I am at wit's end!
It is obvious that function addToEnd is wrong
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
Let's assume that the list already contains two nodes and consider the do-while loop inside the function. At first current_next != null so the following statement is executed
current = current->next;
Now current points to the second node. Its data member next is equal to NULL. So the condition of the loop
} while (current->next != NULL);
will be false and no iteration will be repeated. So we added nothing.
Also the function returns nothing if node is not equal to NULL.
Rewrite the function the following way
listNode* addToEnd( listNode* node )
{
listNode* newNode = new listNode { ++nodeCount, NULL };
if ( node == NULL) return newNode;
listNode* current = node;
while ( current->next != NULL ) current = current->next;
current->next = newNode;
return newNode;
// or
//return node;
}
Take into account that this statement
cout<<"Third: "<<first->next->next->val;
outputs only the value of the third node.
If you want to output all the list you should write
for ( listNode *current = first; current; current = current->next )
{
std::cout << current->val << ' ';
}
std::cout << std::endl;
By the way using my function you could write in main for example the following way:)
listNode* first;
addToEnd( addToEnd( addToEnd( addToEnd( first = addToEnd( NULL ) ) ) ) );
Use a for loop to get you to the last node instead of a while, and then assign the new node OUTSIDE of the loop. Trying to do it inside will result in an infinite loop (and make the code harder to read):
listNode* current;
for(current = node; current->next != NULL; current = current->next) ;
current->next = newNode;
You're also forgetting to return newNode at the end of the function.
You're falling off the end of a function with non-void return type. The fact that you don't use the return value does not make that ok.
6.6.3 in the Standard says that:
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
There is no return statement just in case the if condition that checks if(node==null) fails..
Is it against the rules to use recursive functions in your question?
Why not do...
void addToEnd(listNode* node){
if(node == NULL){
*node = new listNode;
node->next = NULL;
node->val = ++nodeCount;
}else{
addToEnd(node->next);
}
return;
}
int main(){
listNode* first = NULL;
addToEnd(first); // 1
addToEnd(first); // 2
addToEnd(first); // 3
addToEnd(first); // 4
addToEnd(first); // Linked list is now 5 long
}
This is how I would have coded adding five nodes to a linked list that holds a node count. If anyone has advice it is welcome.
#include <iostream>
#include <cstdlib>
using namespace std;
struct listNode{
int val;
listNode* next;
};
listNode* addToEnd(listNode*, int);
int main()
{
listNode* first = NULL;
listNode* temp;
int nodeCount = 1;
for(int i = 0; i < 5; i++){
first = addToEnd(first, nodeCount);
nodeCount++;
}
temp = first;
while(temp){
cout << temp->val << ' ';
temp = temp->next;
}
temp = first;
//Deallocate memory
while(temp){ //could do memory deallocation while displaying
nodeToDelete = temp; //the value of nodeCount but wanted to illustrate
//both methods individually
temp = temp->next;
delete nodeToDelete;
}
first = NULL; //eliminate hanging pointer
return 0;
}
listNode* addToEnd(listNode* node, int nodeCount)
{
listNode* newNode = new (nothrow) listNode;
listNode* current = node;
if(newNode){
newNode->val = nodeCount;
newNode->next = NULL;
if (node == NULL)
node = newNode;
else{
while (current->next != NULL)
current = current->next;
current->next = newNode;
}
}
else
cout << "error allocationg memory" << endl;
return node;
}

Deleting a node in the linklist

Here is my code to delete all the nodes having the value passed in the argument.
typedef struct nodetype
{
int data;
struct nodetype * next;
} node;
typedef node * list;
void Linklist::deleteNode(list * head, int value)
{
list current = *head;
list previous = *head;
while(current != NULL)
{
if(current->data != value)
{
previous = current;
current = current->next;
}
else if (current->data == value)
{
previous->next = current->next;
delete current;
current = previous->next;
}
}
}
But here if all the elements in the linklist is say 2, then it should delete all the elements in the linklist and finally head should also become NULL so that if I pass this head to count the number of nodes in the list it should say that the list is empty and other similar operations.
According to my current implementation the head is not becoming NULL for the above mentioned case.
Please suggest the modification so that head should become NULL if the linklist has all the nodes with the same value passed in the function argument.
I modified my code as follows and its working file now
void Linklist::deleteNode(list *head, int value)
{
list * current = head;
list * previous = head;
bool flag = false;
while(*current != NULL)
{
if((*current)->data != value)
{
*previous = *current;
*current = (*current)->next;
}
else if ((*current)->data == value)
{
flag = true;
(*previous)->next = (*current)->next;
delete *current;
*current = (*previous)->next;
}
}
if(!flag)
cout<<"Element not found in the linklist\n";
cout<<"Count is "<<Linklist::count(*head)<<endl;
}