Insertion and deletion in a stack using linked list - c++

The program is about insertion and deletion in a stack using ling lists.The push works fine but there is problem in the deletion the pop() function has some
error. Every time i try to delete something it gives infinite error with underflow. ie. the top pointer is always null.
#include<iostream>
#include<stdlib.h>
#include<process.h>
using namespace std;
struct node
{
int info;
node *next;
}*top,*save,*newptr,*ptr;
node *create_new_node(int);
void push(node*);
void pop();
void display(node*);
int main()
{
top=NULL;
int inf;
char ch='y';
while(ch=='y'||ch=='Y')
{
newptr=new node;
cout<<"\nEnter the info to be added in the beginning of the stack\n";
cin>>inf;
if(newptr==NULL)
cout<<"\nCannot create new node.ABORTING!!\n";
else
{
newptr=create_new_node(inf);
cout<<"\nPress enter to continue\n";
system("pause");
}
push(newptr);
cout<<"\nthe info has been inserted in the stack\n";
cout<<"\nThe stack now is\n";
display(newptr);
cout<<"\ndo you wish to add more elements to the stack.\nIf yes then
press y or else press n\n";
cin>>ch;
if(ch=='n'||ch=='N')
{
cout<<"\ndo you to delete elements from the stack\n";
cout<,"\nIf yes then press d else press n\n";
cin>>ch;
if(ch=='d'||ch=='D')
{
while(ch=='d'||ch=='D')
{
pop();
cout<<"\npress d to delete more elements y to add more
elements and n to exit\n";
cin>>ch;
}
}
}
}
delete(ptr);
delete(newptr);
delete(top);
delete(save);
return 0;
}
node* create_new_node(int n)
{
ptr=new node;
ptr->info=n;
ptr->next=NULL;
return ptr;
}
void push(node *np)
{
if(top==NULL)
top=np;
else
{
save=top;
top=np;
np->next=save;
}
}
void pop()
{
if(top==NULL)
cout<<"underflow";
else
{
ptr=top;
top=top->next;
delete ptr;
}
}
void display(node *np)
{
while(np!=NULL)
{
cout<<np->info<<"->";
np=np->next;
}
}

There are multiple bugs in the shown code.
Your main bug:
while(ch=='d'||ch=='D')
{
pop();
cout<<"\npress d to delete more elements y to add more elements and n to exit\n";
}
At this point, when ch is 'd' or 'D' execution will enter the while loop, of course. A call to pop() is made, which removes the topmost element from the stack, prints a message, and repeats the while loop.
At this point your program will make an important discovery that ch is still either 'd' or 'D'. Nothing has changed its value. A computer program always does exactly what you tell it to do, unfortunately, instead of what you think you want it to do. No matter how hard you look here, you will never find any code here that ever changes the value of ch. It will remain at its current value forever. And so the while loop runs again. And again. And again. Nothing ever changes the value of ch, at this point, so you have an infinite loop.
Additionally, in your main:
newptr=new node;
This pointer's value is later compared to NULL; and if not ... it gets completely overwritten by
newptr=create_new_node(inf);
This accomplishes absolutely nothing, except leaking memory. This code appears to be leftover junk, and should be cleaned up after fixing the faulty while loop logic.

Related

Problem with display function inside circular queue

#include <stdio.h>
# define MAX 3
int queue[MAX]; // array declaration
int front=-1;
int rear=-1;
// function to insert an element in a circular queue
void enqueue(int element)
{
if(front==-1 && rear==-1) // condition to check queue is empty
{
front=0;
rear=0;
queue[rear]=element;
}
else if((rear+1)%MAX==front) // condition to check queue is full
{
printf("Queue is overflow..");
}
else
{
rear=(rear+1)%MAX; // rear is incremented
queue[rear]=element; // assigning a value to the queue at the rear position.
}
}
// function to delete the element from the queue
int dequeue()
{
if((front==-1) && (rear==-1)) // condition to check queue is empty
{
printf("\nQueue is underflow..");
}
else if(front==rear)
{
printf("\nThe dequeued element is %d", queue[front]);
front=-1;
rear=-1;
}
else
{
printf("\nThe dequeued element is %d", queue[front]);
front=(front+1)%MAX;
}
}
// function to display the elements of a queue
void display()
{
int i=front;
if(front==-1 && rear==-1)
{
printf("\n Queue is empty..");
}
else
{
printf("\nElements in a Queue are :");
while(i<=rear)
{
printf("%d,", queue[i]);
i=(i+1)%MAX;
}
}
}
int main()
{
int choice=1,x; // variables declaration
while(choice<4 && choice!=0) // while loop
{
printf("\nPress 1: Insert an element");
printf("\nPress 2: Delete an element");
printf("\nPress 3: Display the element");
printf("\nEnter your choice");
scanf("%d", &choice);
switch(choice)
{
case 1:
printf("Enter the element which is to be inserted");
scanf("%d", &x);
enqueue(x);
break;
case 2:
dequeue();
break;
case 3:
display();
}}
return 0;
}
I have problem with display function how can i print all element if rear can be in somecases less than front for example in this code i try to enqueue 3 elements 1,2,3 then dequeue two elements which i mean here 1,2 after that i try to enque two elements 1,2 again finaly when i try to display elements i get nothing so what is the perfect way to display queue elements
So... here's a working solution.
#include <stdio.h>
# define MAX 3
class CircularQueue
{
private:
int queue[MAX]; // array declaration
int front;
int rear;
public:
CircularQueue() :
front(-1),
rear(-1)
{ }
// function to insert an element in a circular queue
void enqueue(int element)
{
if(front==-1 && rear==-1) // condition to check queue is empty
{
front=0;
rear=0;
queue[rear]=element;
}
else if((rear+1)%MAX==front) // condition to check queue is full
{
printf("Queue is overflow..\n");
}
else
{
rear=(rear+1)%MAX; // rear is incremented
queue[rear]=element; // assigning a value to the queue at the rear position.
}
}
// function to delete the element from the queue
void dequeue()
{
if((front==-1) && (rear==-1)) // condition to check queue is empty
{
printf("Queue is underflow..\n");
}
else if(front==rear)
{
printf("The dequeued element is %d\n", queue[front]);
front=-1;
rear=-1;
}
else
{
printf("The dequeued element is %d\n", queue[front]);
front=(front+1)%MAX;
}
}
// function to display the elements of a queue
void display()
{
if(front==-1 && rear==-1)
printf("Queue is empty..\n");
else
{
printf("Elements in a Queue are: ");
int i=front;
do
{
if (i != front)
printf(",");
printf("%d", queue[i]);
i=(i+1)%MAX;
} while (i != (rear+1)%MAX);
printf("\n");
}
}
};
int main()
{
CircularQueue cq;
unsigned int choice=1; // variables declaration
while(choice<4 && choice!=0) // while loop
{
printf("Press 1: Insert an element\n");
printf("Press 2: Delete an element\n");
printf("Press 3: Display the element\n");
printf("Press any other number to exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch(choice)
{
case 1:
printf("Enter the element which is to be inserted: ");
int x;
scanf("%d", &x);
cq.enqueue(x);
break;
case 2:
cq.dequeue();
break;
case 3:
cq.display();
}
}
return 0;
}
I made a couple of changes to the output, see the positions of the \n. Its always good to give the next print statement a new line to write to if the current output is complete.
The biggest change, I put everything in a class. That way you don't have any global variables, which is to 99.999% a bad thing. Your code is very C like, so normally I would use std::cout as well and with std::vector you could easily make you buffer have arbitrary size.
Here's some output:
Press 1: Insert an element
Press 2: Delete an element
Press 3: Display the element
Press any other number to exit
Enter your choice: 1
Enter the element which is to be inserted: 2
Press 1: Insert an element
Press 2: Delete an element
Press 3: Display the element
Press any other number to exit
Enter your choice: 3
Elements in a Queue are: 2
Press 1: Insert an element
Press 2: Delete an element
Press 3: Display the element
Press any other number to exit
Enter your choice: 4
TL;DR version: The hard part of making a circular buffer is telling the full condition from the empty condition because they are both front == rear unless you take extra steps like tracking the size or maintaining a bool full; or preventing rear from catching up to front.
I like the latter approach because it makes for really simple code. I like writing simple code. You don't have to think as hard debugging it. You don't have to spend as much time writing it. You don't get bothered by the maintenance team supporting it. Simple code is only a problem when it's too simple and misses a case.
So I'm going for simple here.
Embedding comments where I feel it's appropriate because explanation is easier to understand when it's right up close to what it is explaining.
#include <stdio.h>
// made MAX one bigger
// If we waste a space in the queue the only time front can be the same as rear
// is if the queue is empty. No ambiguity. No special code for special cases or
// extra tracking variables to tell full from empty.
// All for the low, low price of one queue element.
# define MAX 4
// in full on c++ this would be constexpr int MAX = 4;
// In general avoid macros because they are really stupid. With a macro any
// token MAX will be replaced with 4 no matter how bad an idea it is. The
// resulting compiler errors get really weird.
// with a constexpr, the compiler will not substitute anything and will take
// context into account, giving much better diagnostics if you screw up
int queue[MAX]; // array declaration
// Don't comment the obvious stuff
// it just clutters up the code and makes you look... well..
// Hey, look! Dummy here needs a comment to rem'ber he's
// defining an array! HA HA HA HA HA!
// You've got better things to do than put up with smurf like that.
int front=0;
int rear=0;
// global variables suck. Because a global can be changed by anything at any
// time tracking errors is a pain in the neck. Every function could have
// unexpected side effects and needs to be examined while debugging.
// Plus because these variables are global and shared, you can only ever have
// ONE queue and EVERYBODY can use it.
// These variables and the queue-handling functions should be in a queue class,
// and there should be an instance of this class defined in main.
// helper functions to keep repetition down.
// Also a well-named helper makes what's happening brutally obvious to anyone
// reading the code
int advance(int pos)
{
return (pos+1)%MAX;
}
bool empty()
{
return front == rear;
}
bool full()
{
return front == advance(rear);
// because of the wasted space telling full from empty is dead easy
}
// function to insert an element in a circular queue
void enqueue(int element)
{
if(full()) // see? Much easer to read than if (front == (rear+1)%MAX)
// now we barely need to comment.
{
printf("Queue is overflow.\n");
}
else
{
queue[rear]=element;
rear = advance(rear);
}
}
// function to delete the element from the queue
void dequeue()
{
if(empty())
{
printf("Queue is underflow.\n");
}
else
{
printf("The dequeued element is %d\n", queue[front]);
front = advance(front);
}
}
// function to display the elements of a queue
void display()
{
if(empty())
{
printf("Queue is empty.");
}
else
{
int i = front;
printf("Elements in a Queue are :");
while(i!=rear)
{
printf("%d,", queue[i]);
i = advance(i);
}
}
printf("\n");
}
// test the logic in small chunks. Make sure the queue works perfectly before
// slapping in a menu system. If there's a bug, you don't have to ask if it's
// in the menu or in the queue because you're only testing one thing at a time
// when you know they both work separately, put 'em together and test again
// just to be on the safe side.
int main()
{
display();
enqueue(1);
display();
dequeue();
display();
enqueue(2);
display();
enqueue(3);
display();
enqueue(4);
display();
enqueue(5); // fail
display();
enqueue(6); // fail
display();
dequeue();
display();
dequeue();
display();
dequeue();
display();
dequeue(); // fail
display();
dequeue(); // fail
display();
return 0;
}

Why my program keep asking values continuously if I add this line

I am trying to increase the value of s by the call by reference but when I add *s=*s+5; my code is going to a loop of continuously getting values
#include<iostream>
using namespace std;
class node
{
public:
int data;
node *next;
};
node* push(node *head,int newdata,int *s)
{
node *newnode,*temp;
newnode=new node;
newnode->data=newdata;
if(head==0) head=temp=newnode;
else
{
newnode->next=head;
head=newnode;
}
*s=*s+5; //this line
return head;
}
void print(node *head,int s)
{
for(int i=0;i<s;i++)
{
cout<<endl<<head->data;
head=head->next;
}
}
int main()
{
node *head=0;
int s,a;
cin>>s;
for(int i=0;i<s;i++){
cin>>a;
head=push(head,a,&s);
}
print(head,s);
cout<<endl<<endl<<s;
return 0;
}
You are getting an infinite loop because i < s is always true since you increase s by 5 on every push function call. Here's your loop:
for(int i=0; i<s; i++){
After every iteration it checks whether i < s. But you are increasing s by 5 in the function push():
*s=*s+5; //this line
Thus, i is always less than s and the loop keeps on looping. Think of this like, i is trying to catch s but everytime i takes a step, s takes 5 steps and runs away. Thus, i is never able to catch s and hence your loop never finishes.
If you keep on looping some day s will become so huge that it will not be able to increase any more and it will overflow. Thus you will enter the realm of undefined behaviour. Undefined behaviour means that no one knows exactly what will happen. Anything can happen, but most likely your program will crash. But it can do other bad things, so you should quickly fix this by not changing s while the loop is looping :)

Why does this code crash while testing stack?

OK, so I edited my code, but I still have two problems :
But here's my code first :
#include <iostream>
using namespace std;
struct stack
{
int data[5];
int top;
};
void push (int a, stack &S)
{
S.top++;
if (S.top<5)
{
S.data[S.top]=a;
}
else cout<<"Stack is full!!!"<<endl; S.top--;
}
int pop(stack &S)
{
if (S.top==-1)
{
cout<<"Stack is empty!"<<endl;
}
else
{
int temp=S.data[S.top];
S.data[S.top]=NULL;
S.top--;
return temp;
}
}
bool isEMPTY(stack &S)
{
if (S.top==-1)
return true;
else return false;
}
bool isFULL(stack &S)
{
if (S.top==5)
return true;
else return false;
}
int main()
{
stack S = { {}, -1 };
push(5,S); cout<<"5 is pushed \n"<<endl;
push(3,S); cout<<"3 is pushed \n"<<endl;
push(1,S); cout<<"1 is pushed \n"<<endl;
push(2,S); cout<<"2 is pushed \n"<<endl;
push(6,S); cout<<"6 is pushed \n"<<endl;
push(7,S); cout<<"7 is pushed \n"<<endl;
cout<<pop(S)<<"is popped\n"<<endl;
cout<<pop(S)<<"is popped\n"<<endl;
cout<<pop(S)<<"is popped\n"<<endl;
return 0;
}
So, the first problem is, when I pop I get a "Totally random value" and it's not like LIFO.
Second is, I actually intended on inserting 6 values, when I already had the max value = 5, so the output actually showed me the 6 values.
stack S;
Since stack is POD, the above line doesn't initialize the member top. As such, using an uninitialized top in push and pop functions invokes undefined behavior.
Write this:
stack S {}; //must be compiled in C++11 mode, else write : stack S = stack();
This value-initializes S and its members, which means, top is initialized to 0. The rest of the code may still have other problems, but at least you have fixed the issues with proper initialization. If you work with 0 as initial value of top, you've write the logic of push and pop accordingly!
Once you fix that, check the value of top before pushing and poping values from the stack, as the member array can have at most 5 elements, and you cannot pop more elements when it is empty. You must maintain these invariants.
I do not see where an object of type stack was created and how data member top was initialized.
Also take nto account that member function push does not check whether there is an attempt to add an item beyond the array.
You should define the object the following way
stack S = { {}, -1 };
else cout<<"Stack is full!!!"<<endl; S.top--;
is identical to :
else
{
cout<<"Stack is full!!!"<<endl;
}
S.top--;
as a general rule, try to avoid: writing if/else without curly brackets, and, avoid writing more then one line of code in the same line.
The mistake is:
stack s;//you define the local variable "s" without been intitialized.
push(5,s);//pass the uninlitialized "s" to the function "push",when debugging your code,"s.top" is not a expected "-1",but some value incredible~(often extreamly larger than 5),so your push operation failed!
stack S;
S.top = -1;
for(int i = 0; i < 5; i++)
{
S.data[i] = 0;
}

Queue using Array>>shifting elements after popping

I'm trying to implement a queue using an array. Here is my code:
#include <iostream.h>
#define SIZE 5
class queue
{
int *Queue, front, rear;
public:
queue() {
Queue = new int[SIZE];
front = rear = -1;
}
void push() {
if (rear == (SIZE-1)) {
cout<<"\n Overflow!";
} else {
rear++;
cout<<"\n Enter element: ";
cin>>Queue[rear];
}
}
void pop() {
if (front == rear) {
cout<<"\n Underflow!";
} else {
cout<<"\nElement popped: "<<Queue[++front];
}
}
void display() {
if (front == rear) {
cout<<"\n Queue Empty";
} else {
for(int i = (front+1); i<=rear; i++) {
cout<<Queue[i]<<" ";
}
}
}
};
int main()
{
int choice;
queue q;
while(choice != 4)
{
cout<<"\n\n Enter your choice :"
<<"\n 1. Push an element into Queue."
<<"\n 2. Pop an element from Queue."
<<"\n 3. Display the Queue."
<<"\n 4. Exit the program.\n\n";
cin>>choice;
switch (choice) {
case 1:
q.push();
break;
case 2:
q.pop();
break;
case 3:
q.display();
break;
case 4:
break;
}
}
return 0;
}
The thing is that once the overflow is met, even after popping an element the rear remains the same and another element is not added when there is a vacant space where it can go.
The solution for this could be to shift every element one place ahead so that there is empty spot at the end but I am having trouble with the shift. Also, if I try inserting after popping 2-3 times before reaching overflow then it still gives overflow even when there are only 3 elements in the queue.
How can I solve this?
You never reset front or rear, they keep increasing forever.
the overlflow test is also wrong:
if (rear == (SIZE-1)) {
cout<<"\n Overflow!";
what you should be testing is if your are about to overwrite front. I think you will benefit from keeping just front and the number of elements N instead. Then overflow and underflow becomes N>SIZE and N==0 instead. Then just increase and decrease N as you pop and push. Keep front as it is but also keep it modulo SIZE.
Also, as written in a comment. No need to move around the data.
Implement a Circular Buffer to avoid the need to shift the whole data.

Error in a Link List

I wrote the following code for a Link list to create a Book its serial no. and search it. I am using linked list in it.
When I add my first entry , it is added successfully, but when I add second entry it shows segmentation fault. I am not able to figure out why. Please help.Thanks in advance.Code:
#include<iostream>
#include<string>
#include<fstream>
#include<cstdlib>
using namespace std;
struct book
{
int accno;
string name;
book* next;
};
int main()
{
bool flag=false;
int x,m;
string s;
book* front=NULL;
book* n;
do
{
cout<<"\nPlease select the following:\n1.Create and append\n2.Search\n3.Exit";
cin>>m;
switch(m)
{
case 1:
n=new book();
cout<<"\nEnter the book name: ";
cin>>s;
cout<<"\nEnter the acc no.: ";
cin>>x;
if(front==NULL)
{
front=n;
}
else
{ n=front;
while(n->next!=NULL)
{
n=n->next;
}
n=n->next;
}
n->accno=x;
n->name=s;
break;
case 2:
cout<<"Enter the roll no.";
int y;
cin>>y;
if(front==NULL){cout<<"Doesnot exist\n"; break;
}
else
{
n=front;
while(n->accno!=y && n->next!=NULL)
{
n->next=n;
}
cout<<"Book name is:"<<n->name;
cout<<"\nAccno is: "<<n->accno;
}
break;
case 3: flag=true;
break;
}
}
while(flag==false);
return 0;
}
Here
while(n->next!=NULL)
{
n=n->next;
}
n=n->next;
you iterate through the linked list to find the last element, then step past it. After this, n will be null.
What you are missing is creating a new element and appending it to the end of the list.
And here
n->accno=x;
n->name=s;
you must also assign n->next = null, otherwise your list won't be properly terminated.
Also, when searching for a book, here
while(n->accno!=y && n->next!=NULL)
{
n->next=n;
}
cout<<"Book name is:"<<n->name;
cout<<"\nAccno is: "<<n->accno;
after exiting the loop, either you found the book or n is null. You must check which is the case before trying to dereference n, otherwise you will again get a segfault if the book you are looking for is not in the list.
Learn to write a linked list (so if this is a homework targeted at learning them, it's valid, but it is not tagged as such), but never ever do it in practice. There is a standard library and there is boost and they have all data structures you'll need unless you do something really special.
You have C++, so don't write C-style code. book should have a constructor that should initialize it's members. The list head should probably be encapsulated in the class too and manipulated using it's methods.
You never set n->next, so don't be surprised it never contains anything meaningful.
You re-use n in the loop forgetting the object you constructed (memory leak).
Than you get the NULL at the end of the list instead of the object you constructed.
here lies your problem:
....
else
{
n=front;
while(n->next!=NULL) //access to next will cause seg fault!!!
{
n=n->next;
}
n=n->next; // step once more, now we have NULL on second add...
}
also, where is n->next being assigned? I don't see it anywhere?
What are you doing here?
case 1:
n=new book();
cout<<"\nEnter the book name: ";
cin>>s;
cout<<"\nEnter the acc no.: ";
cin>>x;
if(front==NULL)
{
front=n;
}
else
{
n=front;
}
while(n->next!=NULL)
{
n=n->next;
}
n=n->next;
}
n->accno=x;
n->name=s;
break;
You have created new book and assigned it to n, in first case its ok becasue your are directly assigning it to front. But in other case you should iterate list using someother variable (temp), when your write n = front, your have already lost your new book object pointer. Hope you got your answer.
This is a buggy code:
You need null the "next" field when you add a new node:
case 1:
new book();
n->next = NULL;
...
You have the memory leakage