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

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

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

c++ replace values in linked list by changing pointers

Having a problem with linked list. Need to create a method, which will replace data in list, by not creating a new element but by changing pointers. For now I have such method:
void replaceValues(Node* head, int indexOne, int indexTwo)
{
Node* temporaryOne = NULL;
Node* temporaryTwo = NULL;
Node* temp = NULL;
Node* current = head;
int count = 0;
while (current != NULL) {
if (count == indexOne)
{
temporaryOne = current;
}
else if (count == indexTwo)
{
temporaryTwo = current;
}
count++;
current = current->next;
}
current = head;
count = 0;
while (current != NULL) {
if (count == indexOne)
{
head = temporaryTwo;
}
else if (count == indexTwo)
{
head = temporaryOne;
}
count++;
current = current->next;
}
}
I am sure, that exists a more simpler way, how to do it, but I don't fully understand, how it works...
Thanks in advance for help.
I assume that with "replace" you actually mean "swap"/"exchange".
Some issues:
The argument head should be passed by reference, as one of the nodes to swap may actually be that head node, and then head should refer to the other node after the function has done its job.
The node before temporaryOne will need its next pointer to change, so you should stop your loops one step earlier in order to have access to that node and do that.
In some cases head may need to change, but this is certainly not always the case, so doing head = temporaryOne or head = temporaryTwo is certainly not right. In most cases you'll need to link to the swapped node from the preceding node (see previous point).
The next pointer of the node that is swapped will also need to change, as the node that follows it will be a different one than before.
As mentioned already in comments, it is advised to split the task into removals and insertions, as the fiddling with next pointers can get confusing when you try to cover all possible cases, notably making the distinction between the case where the two nodes are adjacent and when they are not.
Here are some functions that split the work into removal, insertion and finally exchanging nodes:
Node* removeNode(Node* &head, int index) {
// If index is out of range, no node is removed, and function returns nullptr
// Otherwise the extracted node is returned.
if (head == nullptr || index < 0) return nullptr;
Node* current = head;
if (index == 0) {
head = head->next;
current->next = nullptr;
return current;
}
while (--index > 0) {
current = current->next;
if (current == nullptr) return nullptr;
}
Node* temp = current->next;
if (temp != nullptr) {
current->next = temp->next;
temp->next = nullptr;
}
return temp;
}
void insertNode(Node* &head, Node* node, int index) {
// If index is too large, node is inserted at the end of the list
// If index is negative, node is inserted at the head of the list
if (index <= 0 || head == nullptr) {
node->next = head;
head = node;
return;
}
Node* current = head;
while (--index > 0 && current->next != nullptr) {
current = current->next;
}
node->next = current->next;
current->next = node;
}
bool exchangeNodes(Node* &head, int indexOne, int indexTwo)
{
// Returns true when successful, false when at least one index
// was out of range, or the two indexes were the same
if (head == NULL || head->next == NULL || indexOne == indexTwo || indexOne < 0) return false;
// To ensure the right order of operations, require the first index is the lesser:
if (indexOne > indexTwo) return exchangeNodes(head, indexTwo, indexOne);
Node* two = removeNode(head, indexTwo);
if (two == nullptr) return false; // out of range
Node* one = removeNode(head, indexOne);
insertNode(head, two, indexOne);
insertNode(head, one, indexTwo);
return true;
}

Linked list head pointer not getting updated when called by reference

I have written two functions to insert nodes in a Linked List. While one function (insertNth) updates the head pointer, the second one (sortedInsert) does not update the head pointer across function calls. The push function is taking a reference to the head pointer.
struct node
{
int data;
node *next;
};
void printList(node *head)
{
node *current = head;
while(current!=NULL)
{
cout<<current->data<<" ";
current = current->next;
}
}
void push(node* &head, int data)
{
node *newNode = new node();
newNode->data = data;
newNode->next = head;
head = newNode;
}
void insertNth(node *&head, int index, int val)
{
node *current = head;
int cnt = 0;
while(current!=NULL)
{
if(cnt == index)
{
if(cnt==0)
{
push(head, val);
}
else
{
push(current->next, val);
}
}
current=current->next;
cnt++;
}
}
void sortedInsert(node *head, int val)
{
node *current = head;
if(head != NULL && val < head->data)
{
node *newNode = new node();
push(head,val);
return;
}
while(current!=NULL)
{
if(current->data < val && current->next->data > val)
{
push(current->next, val);
return;
}
current = current->next;
}
}
int main()
{
node *head;
push(head, 3);
cout<<"\n";
printList(head);
cout<<"\nInsertNth: ";
insertNth(head,0, 2);
printList(head);
cout<<"\nsortedInsert: ";
sortedInsert(head, 1);
printList(head);
return 0;
}
I'm getting following as output:
3
InsertNth: 2 3
sortedInsert: 2 3
Why is the third line not printing 1 2 3?
//
Update
//
The correct SortedInsert is as follows:
void sortedInsert(node *&head, node *newNode)
{
node *current = head;
if(head == NULL || newNode->data < head->data)
{
newNode->next = head;
head = newNode;
return;
}
while(current!=NULL && current->next != NULL)
{
if(current->data < newNode->data && current->next->data > newNode->data)
{
newNode->next = current->next;
current->next = newNode;
return;
}
current = current->next;
}
if(current->next == NULL)
{
current->next = newNode;
newNode->next = NULL;
}
}
A sample was requested. Note that I did it as a template, but you could skip the template business and instead of a T* you can use struct node *. It's not general purpose, but might be easier to understand.
template <class T>
class MyLinkedList {
class Entry {
public:
Entry * previous;
Entry * next;
T * node;
}
Entry * head;
Entry * tail;
void push(T * nodeToPush) { pushBefore(head, nodeToPush); }
void insertNth(int whereToInsert, T * nodeToInsert) {
... find the nth Entry pointer
pushBefore(head, nodeToPush);
}
private:
void pushBefore(Entry *entry, T * nodeToPush) {
Entry *newEntry = new Entry();
newEntry->node = nodeToPush;
if (entry != NULL) {
newEntry->previous = entry->previous;
}
newEntry->next = entry;
entry->previous = newEntry;
if (head == entry) {
head = newEntry;
}
if (tail == NULL) {
tail = newEntry;
}
}
// Other methods as necessary, such as append, etc.
}
Other than passing in a pointer to the objects you're inserting into your linked list, at no point do you have to pass pointers around in a fashion where your methods are also performing side effects on those pointer. The class should know how to manage a class, and no weird passing of variables all over.
Performing side effects on your arguments should be done with GREAT caution. If you're passing an object to a method, then it's fair to manipulate the object. But I really don't like passing pointers and having methods modify the pointers themselves.
That IS going to lead to (at best) confusion.
Note: I did NOT test this code. It might not quite be perfect.

Reversing a linked list starting from the tail using recursion

I still struggle with the recursion technique to solve the problem. I know there are nicer ways to solve my problem below of reversing a linked list. Most of the ways that I have seen, start to reverse the pointers by going from the head to the tail, either by using iteration or recursion.
I am trying for interest to reverse the list by first finding the last node in the list recursively and then changing the pointers everytime the function returns.
What am I doing wrong below exactly? Or will this method even work , without the need to pass more parameters to the recursive function? Thanks in advance for your help.
struct Node
{
int data;
struct Node *next;
};
Node* Reverse(Node *head)
{
static Node* firstNode = head;
// if no list return head
if (head == NULL)
{
return head;
}
Node* prev = NULL;
Node* cur = head;
// reached last node in the list, return head
if (cur->next == NULL)
{
head = cur;
return head;
}
prev = cur;
cur = cur->next;
Reverse(cur)->next = prev;
if (cur == firstNode)
{
cur->next = NULL;
return head;
}
return cur;
}
EDIT : Another attempt
Node* ReverseFromTail(Node* prev, Node* cur, Node** head);
Node* ReverseInit(Node** head)
{
Node* newHead = ReverseFromTail(*head, *head, head);
return newHead;
}
Node* ReverseFromTail(Node* prev, Node* cur, Node** head)
{
static int counter = 0;
counter++;
// If not a valid list, return head
if (head == NULL)
{
return *head;
}
// Reached end of list, start reversing pointers
if (cur->next == NULL)
{
*head = cur;
return cur;
}
Node* retNode = ReverseFromTail(cur, cur->next, head);
retNode->next = cur;
// Just to force termination of recursion when it should. Not a permanent solution
if (counter == 3)
{
cur->next = NULL;
return *head;
}
return retNode;
}
Finally Solved it :
Node* NewestReverseInit(Node* head)
{
// Invalid List, return
if (!head)
{
return head;
}
Node* headNode = NewestReverse(head, head, &head);
return headNode;
}
Node* NewestReverse(Node *cur, Node* prev, Node** head)
{
// reached last node in the list, set new head and return
if (cur->next == NULL)
{
*head = cur;
return cur;
}
NewestReverse(cur->next, cur, head)->next = cur;
// Returned to the first node where cur = prev from initial call
if (cur == prev)
{
cur->next = NULL;
return *head;
}
return cur;
}
I will not give you the code, I will give you the idea. You can implement the idea in the code.
The key to all recursion problems is to figure out two cases: repetition step and end case. Once you do this, it works almost as if magically.
Applying this principle to reversing a linked list:
End case: the list of one element is already reversed (this is straightforward) and returning the element itself
Repetition case: Given list L, reversing this least means reversing an L', where L' is the L' is the list without the very first element (usually called head), and than adding the head as the last element of the list. Return value would be the same as a return value of the recursive call you just made.
It can be done. The key in understanding recursion is What is the starting point?
Usually I create a "starting" function which prepares the first call. Sometimes it is a separate function (like in non OO implemnatation at bottom). Sometimes it's just a special first call (like in example below).
Also the key is in remembering variables before they change and what is the new head.
The new head is the last element of the list. So You have to get it up from the bottom of the list.
The nextelement is always your parent.
Then the trick is to do everything in the correct order.
Node* Reverse( Node* parent) // Member function of Node.
{
Node* new_head = next ? next->Reverse( this )
: this;
next = parent;
return new_head;
}
You call the function with: var.Reverse( nullptr);
Example:
int main()
{
Node d{ 4, nullptr };
Node c{ 3, &d };
Node b{ 2, &c };
Node a{ 1, &b };
Node* reversed = a.Reverse( nullptr );
}
So what is happening here?
First we create a linked list:
a->b->c->d->nullptr
Then the function calls:
a.Reverse(nullptr) is called.
This calls the Reverse on the next node b.Reverse with parent a.
This calls the Reverse on the next node c.Reverse with parent b.
This calls the Reverse on the next node d.Reverse with parent c.
d doesn't have next node so it says that the new head is itself.
d's next is now it's parent c
d returns itself as the new_head.
Back to c: new_head returned from d is d
c's next is now it's parent b
c returns the new_head it recieved from d
Back to b: new_head returned from c is d
b's next is now it's parent a
b returns the new_head it recieved from c
Back to a: new_head returned from b is d
a's next is now it's parent nullptr
a returns the new_head it recieved from b
d is returned
Non object oriented implementation;
Node* reverse_impl(Node* parent)
{
Node* curr = parent->next;
Node* next = curr->next;
Node* new_head = next ? reverse_impl( curr )
: curr;
curr->next = parent;
return new_head;
}
Node* reverse(Node* start)
{
if ( !start )
return nullptr;
Node* new_head = reverse_impl( start );
start->next = nullptr;
return new_head;
}
Here's a full implementation I wrote in 5 minutes:
#include <stdio.h>
struct Node
{
int data;
struct Node *next;
};
struct Node* Reverse(struct Node *n)
{
static struct Node *first = NULL;
if(first == NULL)
first = n;
// reached last node in the list
if (n->next == NULL)
return n;
Reverse(n->next)->next = n;
if(n == first)
{
n->next = NULL;
first = NULL;
}
return n;
}
void linked_list_walk(struct Node* n)
{
printf("%d", n->data);
if(n->next)
linked_list_walk(n->next);
else
printf("\n");
}
int main()
{
struct Node n[10];
int i;
for(i=0;i<10;i++)
{
n[i].data = i;
n[i].next = n + i + 1;
}
n[9].next = NULL;
linked_list_walk(n);
Reverse(n);
linked_list_walk(n+9);
}
Output:
0123456789
9876543210

deleting all specific keys found in linked list

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