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;
}
Related
My program splits the original linked list into halves after I call function binary search function, any way i can keep the original single linked list and calling the function? i did try to create a 2 extra nodes start2 and start1, and tried to copy all of the data of original start into start2 but again it just splits the original linked list.
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
//declaring
struct node{
int info;
struct node* next;
};
node* start= NULL;
node* start1= NULL;
node* start2= NULL;
int count = 0;
void createlist(int value){
node *q,*tmp;
tmp=new(struct node);
tmp->info=value;
tmp->next=NULL;
if(start==NULL) start=tmp; /*if list is empty*/
else /*element inserted at end*/
{
q=start;
while(q->next!=NULL) q=q->next;
q->next=tmp;
}}
int getCount(node* head)
{
// Initialize count
// Initialize current
node* current = head;
while (current != NULL)
{
count++;
current = current->next;
}
return count;
}
int Split( node *start2, node **start1)
{
struct node *slow, *fast;
if(start2->next==NULL) /*only one element*/
return 0;
slow=fast=start2;
while(fast->next!=NULL && fast->next->next!=NULL)
{
slow = slow->next;
fast = fast->next->next;
}
*start1 = slow->next;
slow->next = NULL;
}//End of Split()//
int binarysearch(int number){
start2= start;
getCount(start2);
int midindex;
midindex = count/2;
node* temp;
temp = start2;
int middle= 1;
while(middle != midindex){
temp = temp->next;
middle++;
}
Split(start2, &start1);
if (temp->info == number){
cout<<"The number is at "<<middle <<"index"<<endl;
}
middle++;
if (temp->info<number){
node* temp1 = start1;
while(temp1->info != number){
temp1= temp1->next;
middle++;}
cout<<"The number exist at the "<< middle <<endl;
}
if (temp->info>number){
node* temp2 = start2;
int newcount =1;
while(temp2->info != number){
temp2= temp2->next;
newcount++;
}
cout<<"The number exist at the "<< newcount <<endl;
}
}
void display()
{
struct node *q;
if(start==NULL)
{
cout<<"List is empty"<<endl;
return;
}
q=start;
cout<<"List is:"<<endl;
while(q!=NULL)
{
cout<<q->info<<" ";
q=q->next;
}
cout<<endl;
}
int main(){
int ch, val;
cout<<"1) Push in stack"<<endl;
cout<<"2) Search the number "<<endl;
cout<<"3) Display "<<endl;
cout<<"4) Exit"<<endl;
do {
cout<<"Enter choice: "<<endl;
cin>>ch;
switch(ch) {
case 1: {
cout<<"Enter value to be pushed:"<<endl;
cin>>val;
createlist(val);
break;
}
case 2: {
int n;
cout<<"Enter the value you want to be searched"<<endl;
cin>>n;
binarysearch(n);
break;
}
case 3: {
display();
break;
}
case 4: {
cout<<"Exit"<<endl;
break;
}
default: {
cout<<"Invalid Choice"<<endl;
}
}
}while(ch!=4);
return 0;
}
I'm just trying out implementation of binary tree. It's not for a college class so I cannot ask a teacher :(
I have tried debugging it with the Codeblocks debugger but I'm still not understanding what is going wrong.
I am using class instead of struct. Currently I have only implemented insertion and inorder traversal functions.
For insertion function, I am checking if the root node is NULL or not. If it is NULL, the newNode becomes equal to the root node. Or else, I find the appropriate parent node and then append the newNode as its child.
And, in the inorder traversal function, is my recursion correct?
Edit: Turns out that I wasn't initializing my Node variables. My code is working after initializing those variables. Thanks for your help!
#include<iostream>
using namespace std;
class Node
{
public:
int data;
Node* left_child;
Node* right_child;
};
Node* root = NULL;
void insertion();
void inorder_travesal(Node*);
int main(){
char ch;
do{
int choice;
cout<<"\nEnter your choice: \n1. Insertion\n2. Inorder Traversal\n : ";
cin>>choice;
switch(choice){
case 1: insertion();
break;
case 2: inorder_travesal(root);
break;
}
cout<<"\nDo you want to continue?: ";
cin>>ch;
}while(ch == 'y');
return 0;
}
void insertion(){
int data;
cout<<"\nEnter data: ";
cin>>data;
Node* newNode = new Node;
newNode->data = data;
if(root == NULL)
{
root = newNode;
return;
}
else
{
Node* temp = root;
while(true){
if(temp->data > newNode->data)
{
if(temp->left_child == NULL)
{
temp->left_child = newNode;
return;
}
else
{
temp = temp->left_child;
}
}
else
{
if(temp->right_child == NULL)
{
temp->right_child = newNode;
return;
}
else
{
temp = temp->right_child;
}
}
}
}
inorder_travesal(root);
}
void inorder_travesal(Node* temp){
if(temp->left_child != NULL){
inorder_travesal(temp->left_child);
}
cout<<temp->data<<" ";
if(temp->right_child != NULL){
inorder_travesal(temp->right_child);
}
}
this program is used to delete a node from a linked list.It works fine but the thing is that it prints 0 instead of NOT printing the value of the deleted node.
For ex. If my list is 1-->2-->3-->-999.And I want to delete say 2. Then the final list is printed as 1-->0-->-->3-->-999.Why the 0???
enter code here
#include<stdio.h>
#include<malloc.h>
struct list {
int number;
struct list *next;
};
typedef struct list node;
void create(node *);
void print(node *);
node *delete(node *,int);
main() {
int key;
node *head;
head = (node *)malloc(sizeof(node));
create(head);
printf("Your list as you entered is....................\n");
print(head);
printf("Which element do you want to delete?\n ");
scanf("%d",&key);
head = delete(head,key);
printf("The new list is ..............................\n ");
print(head);
return 0;
}
void create(node *list) {
printf("Enter a number,-999 to stop data entrying\n");
scanf("%d",&list->number);
if(list->number == -999) {
list->next = NULL;
}
else {
list->next = (node *)malloc(sizeof(node));
create(list->next);
}
}
void print(node *list) {
if(list->number != -999) {
printf("%d-->",list->number);
print(list->next); }
else {
printf("%d",list->number);
}
}
node *delete(node *list,int key) {
node *prev_ptr = NULL;
node *curr_ptr;
for(curr_ptr=list;curr_ptr!=NULL;prev_ptr=curr_ptr,curr_ptr=curr_ptr->next) {
if(curr_ptr->number == key) {
break;
}
}
if(prev_ptr == NULL) {
list = curr_ptr->next;
}
else {
prev_ptr = curr_ptr->next;
}
free(curr_ptr);
return(list);
}
You have a mistake in rearranging the pointers in delete routine.
Instead of
...
else {
prev_ptr = curr_ptr->next;
}
...
You should have
...
else {
prev_ptr->next = curr_ptr->next;
}
...
The 0 is being shown because you free curr_ptr (thus it points to nowhere). But the real issue is you shouldn't have it in the list.
So I created the following bit of code but the display function is giving me problems. It breaks into an infinite loop each time I try using it. Could someone please have a look at it and tell me what's going wrong ?
#include<iostream.h>
#include<conio.h>
struct node{
int info;
node *next;
}*ptr,*start,*temp;
node* create_new()
{
ptr=new node;
cout<<"\nEnter the data: ";
cin>>ptr->info;
ptr->next=NULL;
return ptr;
}
void insert_at_beg()
{
ptr=create_new();
if(start==NULL)
{
start=ptr;
}
if(start!=NULL)
{
ptr->next=start;
start=ptr;
}
}
void display()
{
temp=start;
while(temp->next!=NULL)
{
cout<<"\t"<<temp->info;
temp=temp->next;
}
}
void insert_at_end()
{
if(start==NULL)
{
start=ptr;
}
if(start!=NULL)
{
ptr=create_new();
temp=start;
while(temp->next!=NULL)
{
temp=temp->next;
}
temp->next=ptr;
}
}
void delete_from_end()
{
if(start==NULL)
{
cout<<"NULL LL";
}
else
{
temp=start;
while(temp->next!=NULL)
{
ptr=temp;
temp=temp->next;
}
ptr->next=NULL;
delete temp;
}
}
void delete_from_beg()
{
if(start==NULL)
cout<<"\nNULL LL";
else
start=start->next;
}
void delete_from_mid()
{
int el;
if(start==NULL)
{
cout<<"\nNULL LL";
}
else
{
cout<<"\nEnter element that you want to delete: ";
cin>>el;
temp=start;
while(temp->next!=NULL&&temp->info!=el)
{
ptr=temp;
temp=temp->next;
}
ptr->next=temp->next;
delete temp;
}
}
void main()
{
clrscr();
start=NULL;
temp=NULL;
ptr=NULL;
insert_at_beg();
display();
getch();
}
Your bug is in this code:
void insert_at_beg()
{
ptr=create_new();
if(start==NULL)
{
start=ptr;
}
if(start!=NULL)
{
ptr->next=start;
start=ptr;
}
}
The first time in start will be null, so you'll do start=ptr. However, now if(start!=NULL) will be true, so you'll do ptr->next=start. Since ptr and start both point to the same thing you'll create an infinite loop.
Firstly I would not recommend you to use global variables especially when you have functions that themselves output parameters of the same type (and value).
The problem according to me is in the function insert_at_beg():
// yes start is NULL initially
if(start==NULL)
{
start=ptr; // now start is not NULL!!
}
//This statement will also be entered.
if(start!=NULL)
{
ptr->next=start;
start=ptr;
}
}
Instead use an else
if(start==NULL)
{
start=ptr; // now start is not NULL!!
}
else
{
ptr->next=start;
start=ptr;
}
}
Also, instead of:
#include<iostream.h>
#include<conio.h>
Use just #include<iostream>
Your bug that cause infinite loop is somewhere else (insert_at_beg(), I saw that someone already added the details so I won't do this too) in the code.
You still have a problem in your code:
void display()
{
temp=start;
while(temp->next!=NULL)
{
cout<<"\t"<<temp->info;
temp=temp->next;
}
}
You will not print the last elemnt. You stop when the next of the current element (temp) is NULL.
Change this to
while(temp) // equivalent to while(temp !=NULL)
Your display function can be simplified:
void display()
{
node * p = start;
while (p != NULL)
{
cout << "\t" << p->info;
p = p->next;
}
cout << endl; // The side effect of this is to print blank line when empty list.
}
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.