Deleting node using address of previous node - c++

I have a method called Find, which, when the user enters the value of an element, the address gets saved in a new Node called *npt.
Using *npt as an argument, I am supposed to create a delete method which removes the value after the value saved in npt.
For example, if this is my list:
134, 564, 674, 253,and I enter 674 for Find, then 253 gets deleted.
Currently, this is my code for the delete function:
void LinkedList::Delete(Node *PrePosition){
Node *temp = PrePosition -> next;
PrePosition->next = PrePosition->next->next;
delete temp;
}
The problem with this though, is that there is no way to delete the head node currently. The only hint I was given, which does not really help me is this:
PrePosition is NULL if you want to delete the head of the list.

Assuming you have to do a recursive version.
Make a condition for Head. In Find:
Node* find(T value){
if (head->value == value)
return nullptr;
return find(head->next);
Now in Delete:
void Delete(Node * pre) {
Node* temp;
if (pre == nullptr) {
temp = head;
head = head->next;
} else {
temp = pre->next;
pre->next = pre->next->next;
}
delete temp;
}

Related

Pointer in deleting a node in single linked list

In place of *head_ref = temp->next;, why can't I assign it as *head_ref = *head_ref->next?
Why should I use temp? Aren't they pointing to the same place?
class Node{
public:
int data;
Node* next;
};
void deleteNode(Node** head_ref, int key){
Node* temp = *head_ref;
Node* prev = NULL;
if(temp!=NULL && temp->data==key){
*head_ref = temp->next;
delete temp;
return;
}
else{
while(temp!=NULL && *head_ref->data!=key){
prev = temp;
temp = temp->next;
}
}
Your code does not compile, *head_ref->data should be (*head_ref)->data.
The reason why you should use temp is that you want to modify *head_ref only if the element you want to delete is the head element. If you delete any other element of the list, the head pointer must stay the same.
But your code is wrong anyway. You're doing things in the wrong order. You must first find the element you want to delete, and then handle the deletion.
Your code handles the deletion first and then finds the element to delete which is absurd.
You want this:
void deleteNode(Node** head_ref, int key) {
Node* current = *head_ref;
Node* previous = NULL;
// find element to delete
while (current && current->data != key)
{
previous = current;
current = current->next;
}
// if current is NULL here then the element has not been found
if (current != NULL)
{
// element found,
// current points to element found
// previous points to previous element or NULL if current is head
if (previous == NULL)
{
// deleting head element -> we need to update head_ref
*head_ref = current->next;
}
else
{
// deleting any other element -> update next pointer of previous element
previous->next = current->next;
}
delete current;
}
}
That being said, this is rather C code than C++ code. You should use standard containers rather than making your own, or at least use C++ idioms such as constructors.

Why i am getting infinite loop

public void insertion(int data)
{
Node new_node = new Node(data);
if(head==null)
{
head=new_node;
}
new_node.next=head;
head=new_node;
}
I want to insert the new_node when head is null.
I am getting infinite loop of first value which i want to insert in the node
When head == null is true, you essentially do:
head = new_node;
new_node.next = head;
Think about those lines carefully. After the first line runs, head is new_node. With that in mind, the second line is essentially equivalent to
new_node.next = new_node;
Which should highlight the problem. You're setting the new node's tail to itself! That will lead to a cyclic list that will continue infinitely when iterated.
You only want to set head'snextwhenhead*wasn't*null` initially:
public void insertion(int data)
{
Node new_node = new Node(data);
if(head==null)
{
head=new_node;
} else {
new_node.next=head; // Only execute these lines if head already existed
head=new_node;
}
}

Linked List, insert at the end C++

I was writing a simple function to insert at the end of a linked list on C++, but finally it only shows the first data. I can't figure what's wrong. This is the function:
void InsertAtEnd (node* &firstNode, string name){
node* temp=firstNode;
while(temp!=NULL) temp=temp->next;
temp = new node;
temp->data=name;
temp->next=NULL;
if(firstNode==NULL) firstNode=temp;
}
What you wrote is:
if firstNode is null, it's replaced with the single node temp which
has no next node (and nobody's next is temp)
Else, if firstNode is not null, nothing happens, except that the temp
node is allocated and leaked.
Below is a more correct code:
void insertAtEnd(node* &first, string name) {
// create node
node* temp = new node;
temp->data = name;
temp->next = NULL;
if(!first) { // empty list becomes the new node
first = temp;
return;
} else { // find last and link the new node
node* last = first;
while(last->next) last=last->next;
last->next = temp;
}
}
Also, I would suggest adding a constructor to node:
struct node {
std::string data;
node* next;
node(const std::string & val, node* n = 0) : data(val), next(n) {}
node(node* n = 0) : next(n) {}
};
Which enables you to create the temp node like this:
node* temp = new node(name);
You've made two fundamental mistakes:
As you scroll through the list, you roll off the last element and start constructing in the void behind it. Finding the first NULL past the last element is useless. You must find the last element itself (one that has its 'next' equal NULL). Iterate over temp->next, not temp.
If you want to append the element at the end, you must overwrite the last pointer's NULL with its address. Instead, you write the new element at the beginning of the list.
void InsertAtEnd (node* &firstNode, string name)
{
node* newnode = new node;
newnode->data=name;
newnode->next=NULL;
if(firstNode == NULL)
{
firstNode=newnode;
}
else
{
node* last=firstNode;
while(last->next != NULL) last=last->next;
last->next = newnode;
}
}
Note, this gets a bit neater if you make sure never to feed NULL but have all lists always initialized with at least one element. Also, inserting at the beginning of list is much easier than appending at the end: newnode->next=firstNode; firstNode=newnode.
The last element in your list never has it's next pointer set to the new element in the list.
The problem is that you are replacing the head of the linked list with the new element, and in the process losing the reference to the actual list.
To insert at the end, you want to change the while condition to:
while(temp->next != null)
After the loop, temp will point to the last element in the list. Then create a new node:
node* newNode = new node;
newNode->data = name;
newNode->next = NULL;
Then change temps next to this new node:
temp->next = newNode;
You also do not need to pass firstNode as a reference, unless you want NULL to be treated as a linked list with length 0. In that case, you will need to significantly modify your method so it can handle the case where firstNode is NULL separately, as in that case you cannot evaluate firstNode->next without a segmentation fault.
If you don't want to use reference pointer, you could use pointer to pointer. My complete code goes like below:
void insertAtEnd(struct node **p,int new_data)
{
struct node *new_node=(struct node *)malloc(sizeof(struct node));
new_node->data=new_data;
new_node->next=NULL;
if((*p)==NULL)//if list is empty
{
*p=new_node;
return;
}
struct node* last=*p;//initailly points to the 1st node
while((last)->next != NULL)//traverse till the last node
last=last->next;
last->next=new_node;
}
void printlist(struct node *node)
{
while(node != NULL);
{
printf("%d->",node->data);
node=node->next;
}
}
int main()
{
struct node *root=NULL;
insertAtEnd(&root,1);
insertAtEnd(&root,2);
insertAtEnd(&root,3);
insertAtEnd(&root,4);
insertAtEnd(&root,5);
printlist(root);
return 0;
}
Understanding the need of the below two variables is key to understanding the problem:
struct node **p: Because we need to link it from the root node created in the main.
struct node* last: Because if not used, the original content will be changed with the contents of the next node inside the while loop. In the end only 2 elements will be printed, the last 2 nodes, which is not desired.
void addlast ( int a)
{
node* temp = new node;
temp->data = a;
temp->next = NULL;
temp->prev=NULL;
if(count == maxnum)
{
top = temp;
count++;
}
else
{
node* last = top;
while(last->next)
last=last->next;
last->next = temp;
}
}
#include <bits/stdc++.h>
using namespace std;
class Node
{
public:
int data;
Node *next;
};
void append(Node *first, int n)
{
Node *foo = new Node();
foo->data = n;
foo->next = NULL;
if (first == NULL)
{
first = foo;
}
else
{
Node *last = first;
while (last->next)
last = last->next;
last->next = foo;
}
}
void printList(Node *first)
{
while (first->next != NULL)
{
first = first->next;
cout << first->data << ' ';
}
}
int main()
{
Node *node = new Node();
append(node, 4);
append(node, 10);
append(node, 7);
printList(node);
return 0;
}
Output: 4 10 7
You can use this code:
void insertAtEnd(Node* firstNode, string name)
{
Node* newn = new Node; //create new node
while( firstNode->next != NULL ) //find the last element in yur list
firstNode = firstNode->next; //he is the one that points to NULL
firstNode->next = newn; //make it to point to the new element
newn->next = NULL; //make your new element to be the last (NULL)
newn->data = name; //assign data.
}
void InsertAtEnd (node* &firstNode, string name){
node* temp=firstNode;
while(temp && temp->next!=NULL) temp=temp->next;
node * temp1 = new node;
temp1->data=name;
temp1->next=NULL;
if(temp==NULL)
firstNode=temp1;
else
temp->next= temp1;
}
while loop will return at temp==null in your code instead you need to return last node pointer from while loop like this
while(temp && temp->next!=NULL) temp=temp->next;
and assign a new node to next pointer of the returned temp node will add the data to the tail of linked list.

Printing Linked List in C++

My following code print just only first element. In print_list() function, it stops after printing first element. It says after first element, head->next is 0. Shouldn't point towards second element?
I want to simply print whole list.
#include<iostream>
#include<cstdlib>
using namespace std;
struct node {
int x;
node *next;
};
node* add_element(node*);
bool is_empty(node*);
void print_list(node*);
node* search(node*);
int main()
{
node *head;
head=NULL;
node* current=head;
for(int i=0;i<5;i=i+1)
{
if (current==NULL)
{
current=add_element(current);
head=current;
}
else{
current=add_element(current);
}
}
cout<<head->next<<endl;
// DOUBT: head->next gives NULL value. It should give me pointer to 2nd node
print_list(head);
}
node* add_element(node* current)
{
node* temp;
temp=new node;
temp->next=NULL;
cout<<"enter element"<<endl;
cin>>temp->x;
current=temp;
return current;
}
bool is_empty(node* temp)
{
return temp==NULL;
}
void print_list(node* temp)
{
if (is_empty(temp)==false)
{
cout<<"here temp(head)"<<temp->next<<endl;
while(temp!=NULL)
{
cout<<temp->x<<endl;
temp = temp->next;
}
}
}
Print function print first element because you have just one node in the Linked List! Actually the mistake is present in add_element(node*) function, you overwrite address of head node with new node (so having memory leak) as I marked below:
node* add_element(node* current)
{
node* temp;
temp = new node; <---" You allocated memory"
temp->next = NULL; <---" Set next NULL"
cout<< "enter element" << endl;
cin>> temp->x; <---" Assign a value in new node"
// Replace below two line with suggested
current = temp; <---"MISTAKE: Overwrite first node"
"temp next is NULL so losing address of other nodes"
return current; <--- "return first node"
}
Next of new node (so first node) is NULL hence the print function prints only first node's value.
Suggestion:
You should Correct as follows to add new node as a first node in linked list:
temp -> next = current; // new nodes next if present first node
return temp; // new code becomes first node
Be careful current should be NULL initially.
With my suggestion in add_element() function also change the for loop code in main() as follows:
for(int i=0; i < 5; i = i + 1){
current = add_element(current);
}
head = current;
And check the working code at Codepade (instead of user input I added value using y = 100 variable).
Edit To append new node:
You need to check whether new node is first node of not (read comments).
// returns first node address in linked list = head
node* add_element(node* head){
node *temp, *new_nd;
// Create new node
new_nd = new node;
new_nd->next = NULL;
cout<<"enter element"<<endl;
cin>>new_nd->x;
// Is new node is the first node?
if(!head)
return new_nd;
// move to last
temp = head;
while(temp->next) temp = temp->next;
// add new node at last
temp->next = new_nd;
// return old head
return head;
}
Also simply main() as below:
int main(){
node *head = NULL;
for(int i = 0; i < 5; i = i + 1){
head = add_element(head);
}
print_list(head);
}
check this working code.
Your problem is here:
node* add_element(node* current)
{
node* temp; //You created a new node
temp=new node; //You allocated it here
temp->next=NULL; //You set its next property to null
cout<<"enter element"<<endl; //
cin>>temp->x;
current=temp; //This should be current->next = temp. You are overwriting it!
return current; //And now you are returning essentially the temp object that
//You created and you set its next property to NULL
}
You are assigning the node you created in temp = new node to the current node that was passed in. What you want to do is assign the node you just created to the current node's next property. It should be current->next = temp
head->next is NULL because you set it so in add_element(). To have a linked list, you should set current->next = temp.
As you're using C++, you might consider using std::list instead of implementing your own linked list.
if (current==NULL)
{ current=add_element(current);
head=current;
}
else
{ current->next=add_element(current);
current=current->next;
}
The correct code.
You have to make a small correction in the loop.
You have to add a new node and then make it point to the next of the current node.
so the simplified code is current->next=add_element(current)
and then make current point to the new current.

How do I delete a node from linked list?

How can I delete a node (between two nodes) from a single linked list without passing any parameters to the class function?
For example, I have a list of 6 nodes with one head node and I want to delete two of them (without prior knowledge of their address or position) from a class function, how would I do that?
void WordList::deleteNode(){
Node *temp;
temp=head;
if(temp->count<=10)
{
//delete this node... not sure how though
}
else
temp=temp->next;
}
where WordList is my class, Node is my struct which holds a word, a count, and a pointer.
I want to delete any node that has a counter of 10 or less.
Your edit has prior information, the bit that states "counter <= 10" :-)
Pseudo-code for deleting elements meeting that criteria in a singly-linked list:
def delLessThanTen:
# Delete heads meeting criteria, stop when list empty.
while head != NULL and head->count <= 10:
temp = head->next
free head
head = temp
if head == NULL:
return
# Head exists, with count > 10, process starting there (we check
# NEXT element for criteria then delete if met).
ptr = head
while ptr->next != NULL:
# If next in list meets criteria, delete it, otherwise advance.
if ptr->next->count <= 10:
temp = ptr->next->next
free ptr->next
ptr->next = temp
else:
ptr = ptr->next
return
I find the question too confusing.
Deletion of a node from the list is always based on some criteria e.g. the content of the element, the position of the element etc (unless you are deleting all the elements in the list)
something like this:
void WordList::deleteNode(){
Node *prev=NULL;
temp=head;
bool done=false;
while (!done)
{
if (temp->count<=10)
{
if (prev == NULL)
{
head = temp->next;
} else
{
prev->next = temp->next;
}
// delete data in temp, and the node if necessary
temp = temp->next;
done = (temp==NULL) || // some other condition, like deleted 2
} else
{
prev=temp;
temp = temp->next;
done = (temp==NULL);
}
}
Have a previous variable initialized to null. If you delete a node, change previous's next to the element's next, unless previous is null (you are at the start of the list) when you leave previous null and change root to the deleted element's next. If you don't delete the element, change previous to the element.
Here previous will always point to the previous element or be null if you're at the start of the list.
void WordList::deleteNode() {
Node *temp = head;
Node *previous = null;
while (temp != null) {
if(temp->count <= 10) {
// delete node
if (previous == null) {
// there is no previous node, so point head of list past the current node
head = temp->next;
} else {
// there is a previous node, so just point it past the current node
previous->next = temp->next;
}
} else {
// not deleting, so set previous to temp
previous = temp;
}
temp = temp->next;
}
}