Deleting node from linked list - c++

The delete from last functionality does not work properly. It shows that the node has been deleted but when I display it, it gets into an infinite loop and displays junk. Couldn't figure what's wrong!
Here's the code:
using namespace std;
class List
{
struct NODE
{
int item;
NODE *next;
};
NODE *Head,*Tail;
public:
List()
{
Head=NULL;
Tail=NULL;
}
~List()
{
while(Head->next!=NULL)
{
Delete_At_Head();
}
Delete_At_Head();
}
void Add_At_First(int);
void Add_At_Last(int);
void Delete_At_Head();
void Delete_At_Tail();
int Is_Empty();
void display();
};
void List::Add_At_First(int data)
{
NODE *temp;
temp=new NODE;
if(Head==NULL)
{
temp->item=data;
temp->next=NULL;
Head=temp;
Tail=Head;
}
else
{
temp->item=data;
temp->next=Head;
Head=temp;
}
cout<<"Node added at first!\n";
}
void List::Add_At_Last(int data)
{
NODE *temp;
temp=new NODE;
temp->item=data;
temp->next=NULL;
if(Head==NULL)
{
Head=temp;
Tail=temp;
}
else
{
Tail->next=temp;
Tail=temp;
}
cout<<"Node added at last!\n";
}
void List::Delete_At_Head()
{
NODE *temp;
temp=new NODE;
temp->item=Head->item;
temp->next=Head->next;
delete Head;
Head=temp->next;
delete temp;
cout<<"Node deleted from head!\n";
}
void List::Delete_At_Tail()//Problematic part
{
NODE *temp,*prev;
temp=new NODE;
prev=new NODE;
temp=Head;
while(temp->next!=NULL)
{
prev=temp;
temp=temp->next;
}
prev->next=NULL;
delete temp;
delete Tail;
Tail=prev;
delete prev;
cout<<"Node deleted from tail!\n";
}
int List::Is_Empty()
{
if(Head==NULL)
return 1;
else
return 0;
}
void List::display()//does not display after delete from tail
{
NODE *temp;
temp=new NODE;
temp->item=Head->item;
temp->next=Head->next;
do
{
cout<<temp->item<<"-->";
temp=temp->next;
}while(temp->next!=NULL);
cout<<temp->item;
}
int main()
{
List obj;
int ch,data;
do
{
cout<<"\n1.Display\n2.Add at first\n3.Add at last\n4.Delete at
head\n5.Delete at tail\n6.Exit\nEnter your choice: ";
cin>>ch;
switch(ch)
{
case 1:
{
if(obj.Is_Empty())
cout<<"List is Empty!\n";
else
obj.display();
break;
}
case 2:
{
cout<<"Enter data: ";
cin>>data;
obj.Add_At_First(data);
break;
}
case 3:
{
cout<<"Enter data: ";
cin>>data;
obj.Add_At_Last(data);
break;
}
case 4:
{
if(obj.Is_Empty())
cout<<"List is Empty!\n";
else
obj.Delete_At_Head();
break;
}
case 5:
{
if(obj.Is_Empty())
cout<<"List is Empty!\n";
else
obj.Delete_At_Tail();
break;
}
case 6:
{
break;
}
}
}while(ch!=6);
return 0;
}

The following should correctly delete the last item in the list:
void List::Delete_At_Tail()
{
if(Head == NULL) return;
// If only one item in the list, delete it and empty the list...
if(Head->next == NULL) {
delete Head;
Head = NULL;
Tail = NULL;
return;
}
// Find the last item in the list
NODE *temp = Head;
while(temp->next!=Tail)
{
temp=temp->next;
}
delete Tail;
temp->next=NULL;
Tail=temp;
cout<<"Node deleted from tail!\n";
}

You are definitely deleting too many objects in your Delete_At_Tail() (I assume this is the function you meant when you wrote delete_from_tail() or "delete from last"; when programming precision is everything!) function: you want to get rid of one object but you are deleteing three objects, including the predecessor of the deleted object. You should only delete the object you are removing and no other. Other than that the function looks OK.
BTW, since you are maintaining a pointer to the Tail you can improve the way to find the predecessor: you can find the node whose next is Tail. This avoids the awkward need to keep two variables up to date in the loop looking for the predecessor.

Related

When I am trying to enter a node between doubly circular linked list it gives wrong output

Here I created a doubly circular linked list and try to add a node between the list but it is giving wrong output
I first created a doubly circular linked list and then displayed it and then I added a node between them and then again displayed it
#include<iostream>
using namespace std;
class node //node class
{
public:
int data;
node *next;
node *prev;
node(int a)
{
data=a;
next=nullptr;
prev=nullptr;
}
};
class linkedlist //linkedlist class
{
node *head,*tail;
public:
linkedlist()
{
head=nullptr;
tail=nullptr;
}
void addnode(int val) //creating node function
{
node *newnode;
newnode=new node(val);
if(head==0)
head=tail=newnode;
else
{
tail->next=newnode;
head->prev=newnode;
newnode->prev=tail;
newnode->next=head;
tail=newnode;
}
}
void disp() //display function
{
node *temp=head;
while(temp->next!=head)
{
cout<<temp->data<<" ";
temp=temp->next;
}
temp=temp->next;
cout<<" "<<temp->data;
}
void addin(int val,int pos) //addin function
{
node *newnode=new node(val);
node *temp=head;
for(int i=0;i<pos;i++)
{
temp=temp->next;
}
newnode->next=temp->next;
newnode->prev=temp;
temp->next->prev=newnode;
temp->next=newnode;
}
};
int main()
{
linkedlist l1;
int s,val,val1,pos;
cin>>s;
for(int i=0;i<s;i++)
{
cin>>val;
l1.addnode(val);
}
l1.disp(); //display function
cout<<"\n\n";
cin>>pos;
cin>>val1;
l1.addin(val,pos); //calling addin function
l1.disp();
}
Input
3
1 2 3
1
0
Expected output
1 2 3
1 2 0 3
Current output
1 2 3 1
I don't know what mistake I am doing and also I am beginner so any tip is also too helpful for me
You are printing the head node instead of the tail node due to the extra temp=temp->next; after the loop in the disp() function.
You are adding val instead of val1 after the loop in the main() function.
void disp() //display function
{
node *temp=head;
while(temp->next!=head)
{
cout<<temp->data<<" ";
temp=temp->next;
}
// remove this
// temp=temp->next;
cout<<" "<<temp->data;
}
cin>>pos;
cin>>val1;
// add val1, not val
//l1.addin(val,pos); //calling addin function
l1.addin(val1,pos); //calling addin function
l1.disp();
in main function
you mistakenly add val instead of val1
cin>>val1;
l1.addin(val1,pos);
then in disp() function, remove temp=temp->next which is outside the loop.
void disp() //display function
{
node *temp=head;
while(temp->next!=head)
{
cout<<temp->data<<" ";
temp=temp->next;
}
// temp=temp->next;
cout<<" "<<temp->data;
}
and finally in addin() function, change pos to pos-1
for(int i=0;i<pos-1;i++)
{
temp=temp->next;
}
that's all.
#MikeCAT was spot on, you are using val1 and passing val. However, I think the while loop in disp will skip the last element and not print it. and the logic in addin are not going to add the new element in the new place. Here is my version of your code
#include<iostream>
using namespace std;
class node //node class
{
public:
int data;
node *next;
node *prev;
node(int a)
{
data=a;
next=nullptr;
prev=nullptr;
}
};
class linkedlist //linkedlist class
{
node *head,*tail;
public:
linkedlist()
{
head=nullptr;
tail=nullptr;
}
void addnode(int val) //creating node function
{
node *newnode;
newnode = new node(val);
if(head == NULL)
head = tail = newnode;
else
{
tail->next = newnode;
head->prev=newnode;
newnode->prev=tail;
newnode->next=head;
tail=newnode;
}
}
void disp() //display function
{
node *temp = head;
if (temp == NULL)
{
cout << "List is empty " << endl;
return;
}
do
{
cout << temp->data << endl;
temp = temp->next;
} while (temp != head);
}
void addin(int val,int pos) //addin function
{
node *newnode=new node(val);
node *temp=head;
for(int i=0;i<pos;i++)
{
temp=temp->next;
}
//newnode->next=temp->next;
newnode->next=temp;
newnode->prev=temp->prev;
temp = temp->prev;
temp->next = newnode;
}
};
int main()
{
linkedlist l1;
int s,val,pos;
cin>>s;
cout << "val of size is " << s << endl;
for(int i=0;i<s;i++)
{
cin>>val;
l1.addnode(val);
}
l1.disp(); //display function
cout<<"\n\n";
cin>>pos;
cin>>val;
l1.addin(val,pos); //calling addin function
l1.disp();
}

Print function isn't working properly- Linked list

I am new to the data structures and I was trying to write a code which add nodes to the beginning of the linked list. After every time user enters a new node, the program is supposed to display an updates linked list, but my program is only displaying the current entered node.
The code is as follows: -
#include<iostream.h>
#include<conio.h>
struct Node
{
int data;
Node* next;
};
struct Node* head;
void Insert(int x)
{
Node* temp=new Node();
temp->data=x;
temp->next=NULL;
head=temp;
}
void Print()
{
struct Node* temp=head;
cout<<"List is: ";
while(temp!=NULL)
{
cout<<temp->data;
temp=temp->next;
}
cout<<"\n";
}
void main()
{
head=NULL;
clrscr();
cout<<"How many numbers?\n";
int n,x,i;
cin>>n;
for(i=0; i<n; i++)
{
cout<<"Enter the number \n";
cin>>x;
Insert(x);
Print();
}
getch();
}
Your Insert method is wrong. You need to assign head to next:
void Insert(int x)
{
Node* temp=new Node();
temp->data=x;
temp->next=head;
head=temp;
}
This will then chain your list correctly.
Your Insert function is wrong. You need to use something like this in order to add new items at the end of the list:
void InsertAtTheEnd(int x) {
Node* temp = new Node();
temp->data=x;
temp->next=NULL;
if (NULL == head) {
head = temp;
} else {
Node *tmp = head;
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = temp;
}
}
And this will add them to the beggining:
void InsertAtTheBeginning(int x) {
Node* temp=new Node();
temp->data=x;
temp->next=head;
head=temp;
}
Check it out live

deletion of a node in a singly linked list

I have made a program in c++ to delete a node in a singly linked list but it is not working as predicted. I am attaching pictures of the output for better clarity that whats misbehaving.
code:
int del_node(int val_del) //this section is producing error
{
node* temp_del=head;
if(head==nullptr)
{
cout<<"no element to delete.!";
exit(0);
}
else
{
while(temp_del->next!=nullptr)
{
if(temp_del->next->data==val_del)
{
temp_del->next=temp_del->next->next;
delete temp_del->next->next;
}
temp_del=temp_del->next;
}
}
return 0;
}
This a function of a class.
Here is the complete code if it helps:
#include<iostream>
using namespace std;
struct node
{
int data;
node *next;
};
class linked_list
{
node *head,*tail;
public:
linked_list()
{
head=nullptr;
tail=nullptr;
}
int create_last(int val_last)
{
node *temp=new node; if(!temp){cout<<"memory not allocated"; exit(1);}
temp->data=val_last;
temp->next=nullptr;
if(head==nullptr)
{
head=temp;
tail=temp;
}
else
{
tail->next=temp;
tail=temp;
}
return 0;
}
int create_beg(int val_beg)
{
node *temp_head=nullptr;
node *temp=new node; if(!temp){cout<<"memory not allocated"; exit(1);}
temp->data=val_beg;
temp->next=nullptr;
if(head==nullptr)
{
head=temp;
tail=temp;
}
else
{
temp_head=head;
head=temp;
temp->next=temp_head;
}
return 0;
}
int del_node(int val_del) //this section is producing error
{
node* temp_del=head;
if(head==nullptr)
{
cout<<"no element to delete.!";
exit(0);
}
else
{
while(temp_del->next!=nullptr)
{
if(temp_del->next->data==val_del)
{
temp_del->next=temp_del->next->next;
delete temp_del->next->next;
}
temp_del=temp_del->next;
}
}
return 0;
}
int show()
{
node* temp_show=head;
while(temp_show!=nullptr)
{
cout<<temp_show->data<<"\n";
temp_show=temp_show->next;
}
return 0;
}
}info;
int main()
{
int choice,ele; char cont;
rep:
cout<<"1. Insert node at the end\n";
cout<<"2. Insert node at beg\n";
cout<<"3. Delete node\n";
cout<<"4. Show nodes\n";
cout<<"5. Exit\n";
cout<<"enter your choice: ";
cin>>choice;
switch(choice)
{
case 1: cout<<"Enter element: ";
cin>>ele;
info.create_last(ele);
break;
case 2: cout<<"Enter element: ";
cin>>ele;
info.create_beg(ele);
break;
case 3: cout<<"Enter element: ";
cin>>ele;
info.del_node(ele);
break;
case 4: info.show();
break;
case 5: exit(0);
break;
default: cout<<"Wrong choice, Bye.!!";
exit(0);
}
cout<<"Do you want to continue(y/n): ";
cin>>cont;
if(cont=='y'||cont=='Y')
{
goto rep;
}
else
{
cout<<"thank you";
exit(0);
}
return 0;
}
int del_node(int val_del) {
node* temp_del = head;
if(head == nullptr) {
cout<<"no element to delete.!";
exit(0);
} else if(head->data == val_del) {
// If head is to be deleted
head = head->next;
} else {
while(temp_del->next != nullptr) {
if(temp_del->next->data == val_del) {
temp_del->next=temp_del->next->next;
// delete temp_del->next->next; This is wrong deletion
}
temp_del = temp_del->next;
}
}
// delete the node if one found else not
if (temp_del != nullptr)
delete temp_del;
return 0; // This should return true or false, do check what you want as return type
}
The del_node function has two problems:
1) It can't delete the node when the list has exactly 1 element
2) It deletes the wrong element
So let's start with number 1 and look at the code:
if(head==nullptr)
{
cout<<"no element to delete.!";
exit(0);
}
else
{
while(temp_del->next!=nullptr)
Assume that the list contains exactly one element. That means:
a) head is not NULL
b) head->next and therefore also temp_del->next is NULL
so while(temp_del->next!=nullptr) will result in false, i.e. the loop will no be executed. The overall result is that the code does nothing.
Now for number 2. The code is:
if(temp_del->next->data==val_del)
{
temp_del->next=temp_del->next->next; // You want to delete temp_del->next
// but here you change it
delete temp_del->next->next; // so here you delete the wrong node
// there is also an extra ->next
}
You need a temp variable to hold a pointer to the node you want to delete.
You probably want the code to be:
int del_node(int val_del)
{
// Delete elements in the front
while (head!=nullptr && head->data==val_del)
{
node* node_to_delete = head;
head = head->next;
delete node_to_delete;
// return 0; Uncomment if you only want one delete per function call
}
if(head==nullptr) return 0;
// Delete elements not in the front
node* temp_del=head;
while(temp_del->next!=nullptr)
{
if (temp_del->next->data==val_del)
{
node* node_to_delete = temp_del->next;
temp_del->next = temp_del->next->next;
delete node_to_delete;
// return 0; Uncomment if you only want one delete per function call
}
temp_del=temp_del->next;
}
return 0;
}

C++ - adding a node to a circular linked list with sorting

I have to create a circular linked list with a function, which adds a node on a particular position (the list should be sorted in ascending order by the value of a variable info). The function is called add_node. I thought that the best would be to create two pointers - to head and to the next node and then use while loop to compare next elements with a new node, and if it gets on a proper place - put it between those two. Unfortunately, the function works only when I add elements with smaller values than the biggest in list. How should this function look like to arrange the nodes correctly?
Code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
class Circular
{
struct node
{
int info;
struct node *next;
}*head;
public:
void create_node(int value);
void add_node(int value);
void display_list();
Circular()
{
head = nullptr;
}
};
void Circular::create_node(int value)
{
node *newnode;
newnode = new node;
newnode->info = value;
if (head == nullptr)
{
head = newnode;
newnode->next = head;
}
else
{
newnode->next = head->next;
head->next = newnode;
head = newnode;
}
}
void Circular::add_node(int value)
{
if (head == nullptr)
{
cout<<"List has not been created yet"<<endl;
return;
}
node *newnode, *ptr2, *ptr1;
newnode = new node;
newnode->info = value;
newnode->next=nullptr;
ptr1=head;
ptr2=head->next;
while(newnode->info > ptr2->info)
{
ptr1 = ptr1->next;
ptr2 = ptr2->next;
if(ptr2 == head) break;
}
ptr1->next = newnode;
newnode->next = ptr2;
}
void Circular::display_list()
{
node *s;
if (head == nullptr)
{
cout<<"List is empty"<<endl;
return;
}
s = head->next;
cout<<"Circular Link List: "<<endl;
while (s != head)
{
cout<<s->info<<"->";
s = s->next;
}
cout<<s->info<<endl<<endl;
}
int main()
{
int choice, element;
Circular cl;
while (1)
{
cout<<"1.Create node"<<endl;
cout<<"2.Add node"<<endl;
cout<<"3.Display"<<endl;
cout<<"9.Quit"<<endl;
cout<<"Enter your choice : ";
cin>>choice;
switch(choice)
{
case 1:
cout<<"Enter the element: ";
cin>>element;
cl.create_node(element);
cout<<endl;
break;
case 2:
cout<<"Enter the element: ";
cin>>element;
cl.add_node(element);
cout<<endl;
break;
case 3:
cl.display_list();
break;
case 9:
exit(1);
break;
default:
cout<<"Wrong choice"<<endl;
}
}
return 0;
}
I've come up with this:
void Circular::add_node(int value)
{
node *newnode, *ptr2, *ptr1, *temp;
newnode = new node;
newnode->info = value;
newnode->next=nullptr;
if (head == nullptr)
{
head = newnode;
newnode->next = head;
}
ptr1=head;
ptr2=head->next;
while(newnode->info > ptr2->info)
{
ptr1 = ptr1->next;
ptr2 = ptr2->next;
if(ptr2 == head) break;
}
if( ptr2->info < newnode->info )
{
temp=new node;
temp->info= ptr2->info;
temp->next= ptr2->next;
ptr2->next=newnode;
newnode->next=temp->next;
head=newnode;
delete temp;
}
else
{
ptr1->next = newnode;
newnode->next = ptr2;
}
}
It seems that it works. However, I wonder is there a better way to do it?
If a node is inserted before head, then then the last node's next pointer is not updated to point to the new head node, and the code currently doesn't have an easy way to find the last node in the list.
The usual way to handle this is also have tail pointer (pointer to the last node). Since this is a circular list, you only need to maintain a tail pointer for the class, since head can be created at anytime using head = tail->next;
Optional: add_node can be updated to handle an empty list, eliminating the need for create_node.

Linked List access violation

I get this error during execution.
You see I had a free(temp) before the
cout<<
statements.I removed them.I thought it was because of bad dereferencing turns out its something more to it.
This is my program:
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
using namespace std;
struct node{
int data;
node* next;
};
node* head=NULL;
node* current=NULL;
void insert_node()
{
int num=0;
cout<<"\nEnter the value of the node to insert\n:";
cin>>num;
if(head==NULL)
{
head=(node*)malloc(sizeof(*head));
//current=(node*)malloc(sizeof(*current));
head->data=num;
head->next=NULL;
current=head;
cout<<"Created list\n";
}
else
{
node* temp=(node*)malloc(sizeof(*temp));
temp->data=num;
temp->next=NULL;
current->next=temp;
current=temp;
cout<<"Added element\n";
free(temp);
cout<<"dereferenced element\n";
}
}
void delete_node()
{
if(head!=NULL && head->next==NULL )//only one node
{
current=head=NULL;
cout<<"Deleted Head\n";
}
else if(head!=NULL && head->next!=NULL)//>= 2 nodes
{
node* temp;
//temp=NULL;
temp=head;
while(temp->next!=current)
{
temp=temp->next;
}
temp->next=NULL;
current=temp;
cout<<"Deleted last element\n";
// free(temp);
cout<<"Dereferenced temp\n";
}
else
{
cout<<"delete was not performed";
}
}
void list_linked_list()
{
node* temp=(node*)malloc(sizeof(* temp));
temp=head;
while(temp!=NULL)
{
cout<<temp->data<<"->";
temp=temp->next;
}
cout<<"displayed list\n";
//free(temp);
cout<<"dereferenced temp";
}
void search_node()
{
cout<<"\nenter a number to search";
int search=0,found=0;
cin>>search;
node* temp=(node*)malloc(sizeof(* temp));
temp=head;
while(temp!=NULL)
{
if(temp->data==search)
found=1;
}
if(found==1)
cout<<"found\n";
else
cout<<"not found\n";
//free(temp);
cout<<"dereferenced temp";
}
void main()
{
int n=0;
k:
cout<<"Linked List operations: \n1. insert \n2. delete \n3. search\n 4. view List \n5. Exit";
cin>>n;
switch(n)
{
case 1: insert_node();break;
case 2: delete_node();break;
case 3: search_node();break;
case 4: list_linked_list();break;
case 5: exit(0);break;
default: cout<<" Please enter valid number between 1 and 5";
break;
}
goto k;
}
I dont think i misunderstood linked list concept.
Im pretty clear on it.I think there a mistake with the pointer.
Thank you.
EDIT: NEW CODE:
struct node{
int data;
struct node* next;
};
struct node* head=NULL;
struct node* current=NULL;
void insert_node()
{
int num=0;
cout<<"\nEnter the value of the node to insert\n:";
cin>>num;
if(head==NULL)
{
head->data=num;
head->next=NULL;
current=head;
cout<<"Created list\n";
}
else
{
struct node* temp=(node*)malloc(sizeof(node));
temp->data=num;
temp->next=NULL;
current->next=temp;
current=temp;
cout<<"Added element\n";
cout<<"dereferenced element\n";
}
}
void delete_node()
{
if(head!=NULL && head->next==NULL )//only one node
{
current=head=NULL; //Am I supposed to do anything else here??
cout<<"Deleted Head\n";
}
else
if(head!=NULL && head->next!=NULL)//>= 2 nodes
{
struct node* temp=(node*)malloc(sizeof(node));;
//temp=NULL;
temp=head;
while(temp->next!=current)
{
temp=temp->next;
}
temp->next=NULL;
current=temp;
cout<<"Deleted last element\n";
free(temp->next);
cout<<"Dereferenced temp\n";
}
else
{
cout<<"delete was not performed";
}
}
void list_linked_list()
{
node* temp=(node*)malloc(sizeof(node));
temp=head;
while(temp!=NULL)
{
cout<<temp->data<<"->";
temp=temp->next;
}
cout<<"displayed list\n";
//free(temp); //should I free temp?
cout<<"dereferenced temp";
}
void search_node()
{
cout<<"\nenter a number to search";
int search=0,found=0;
cin>>search;
node* temp=(node*)malloc(sizeof(node));
temp=head;
while(temp!=NULL)
{
if(temp->data==search)
found=1;
else
temp=temp->next;
}
if(found==1)
cout<<"found\n";
else
cout<<"not found\n";
free(temp); //shoudl I free temp?
cout<<"dereferenced temp";
}
There are multiple problems in your code:
You are free()ing a node in your insert function which is not what you want. So remove the line free(temp) from your insert function.
You do want to free the node when you delete an element from your linked list. So uncomment the line: free(temp);. But this is not the correct current node that you want to free(). Here temp is your new current whereas you want to free() your old current which temp->next. So your free() statement should be: free(temp->next); in delete_node() function (Not free(temp); ).
Return value of main should an int.
If you are using C++ there are better ways to implement linked lists. You may want to use new and delete instead of malloc and free. Use C++ headers instead of C headers.
If you do use C, then don't cast the value returned by malloc in C.
You are using goto as a replacement for a loop which is unnecessary when you can simply use for(;;) { } or while(1) { }.
In insert function's else part you free new node just after adding it in Linked List that causes Undefined behaviour at runtime:
else
{
node* temp=(node*)malloc(sizeof(*temp));
temp->data=num;
temp->next=NULL;
current->next=temp;
current=temp;
cout<<"Added element\n";
free(temp); <------"Bug"
cout<<"dereferenced element\n";
}
Note: You can't access a node for which memory is deallocated (free()), doing this is an illegal operation. You should free memory for node when you are done with the program (and don't need access that memory again).