Stack
Stack
STACK
Stack is a Linear Data Structure that follows Last In First Out(LIFO) principle.
Insertion and deletion can be done at only one end of the stack called TOP of the stack.
Example: - Pile of coins, stack of trays
STACK ADT:
STACK MODEL
TOP pointer
Two fundamental operations performed on the stack are PUSH and POP.
(a) PUSH:
1. Stack Overflow
An Attempt to insert an element X when the stack is Full, is said to be stack
overflow.
For every Push operation, we need to check this condition.
2. Stack Underflow:
return(1);
int TopElement(Stack S)
{
if(Top==-1)
{
Error(“Empty stack!!No elements”);
return 0;
}
else
return S[Top];
}
#include<stdio.h>
#include<conio.h>
#define size 5
int stack [ size ];
int top;
void push( )
{
int n ;
printf( "\n Enter item in stack" ) ;
scanf( " %d " , &n ) ;
if( top = = size - 1)
{
printf( "\nStack is Full" ) ;
}
else
{
top = top + 1 ;
stack [ top ] = n ;
}
}
void pop( )
{
int item;
if( top = = - 1)
{
printf( "\n Stack is empty" );
}
else
{
item = stack[ top ] ;
printf( "\n item popped is = %d" , item );
top - -;
}
}
void display( )
{
int i;
printf("\n item in stack are");
for(i = top; i > = 0; i --)
printf("\n %d", stack[ i ] );
}
void main( )
{
char ch,ch1;
ch = 'y';
ch1 = 'y';
top = -1;
clrscr( );
while(ch !='n')
{
push( );
printf("\n Do you want to push any item in stack y/n");
ch=getch( );
}
display( );
while( ch1!='n' )
{
printf("\n Do you want to delete any item in stack y/n");
ch1=getch( );
pop( );
}
display( );
getch( );}
OUTPUT:
Enter item in stack20
Do you want to push any item in stack y/n
Enter item in stack25
Do you want to push any item in stack y/n
Enter item in stack30
Stack is Full
Do you want to push any item in stack y/n
item in stack are
25
20
15
10
5
Do you want to delete any item in stack y/n
item popped is = 25
Do you want to delete any item in stack y/n
item popped is = 20
Do you want to delete any item in stack y/n
item popped is = 15
item in stack are
10
5
Linked list implementation of Stack
Stack elements are implemented using SLL (Singly Linked List) concept.
Dynamically, memory is allocated to each element of the stack as a node.
Type Declarations for Stack using SLL
struct node;
typedef struct node *stack;
typedef struct node *position;
stack S;
struct node{ int
data; position
next;};
int IsEmpty(Stack S);
void Push(int x, Stack S);
void Pop(Stack S);
int TopElement(Stack S);
(i) Stack Empty Operation:
Initially Stack is Empty.
With Linked List implementation, Empty stack is represented as S -> next = NULL.
It is necessary to check for Empty Stack before deleting ( pop) an element from the stack.
Routine to check whether the stack is empty S
Header
30 20 10 NULL
40
newnode
Before Insertion
Push routine /*Inserts element at front of the list
void push(int X, Stack S)
{
Position newnode, Top;
newnode = malloc (sizeof( struct node ) );
newnode -> data = X;
newnode -> next = S -> next;
S -> next = newnode;
Top = newnode;
}
Header
40 30 20 10 NULL
After Insertion
TOP
(iii) Pop Operation
It is the process of deleting the Top element of the stack.
With Linked List implementations, the element at the Front of the List
(i.e.) S -> next is always deleted.
It takes only one parameter. Pop(X).The element X to be deleted from the Front of the
List.
Before deleting the front element in the list, check for Empty Stack.
If the Stack is Empty, deletion is not possible.
Otherwise, make the front element in the list as “temp”.
Update the next field of header.
Using free ( ) function, Deallocate the memory allocated for temp node.
PANIMALA www.padeepz.net
Header
40 30 20 10 NULL
TOP
Before Deletion
Pop routine /*Deletes the element at front of list
void Pop( Stack S )
{
Position temp, Top;
Top = S -> next;
if( S -> next = = NULL)
Error(“empty stack! Pop not possible”);
else
{
Temp = S -> next;
S -> next = temp -> next;
free(temp);
Top = S -> next;
}}
Header
40 30 20 10 NULL
HEADER
30 20 10 NULL
(iv) Return Top Element
Pop routine deletes the Front element in the List.
If the user needs to know the last element inserted into the stack, then the user can
return the Top element of the stack.
To do this, first check for Empty Stack.
If the stack is empty, then there is no element in the stack.
Otherwise, return the element present in the S -> next -> data in the List.
if(S->next==NULL)
error(“Stack is empty”);
return 0;
else
return S->next->data;
}
S
Header
40 30 20 10 NULL
TOP
Implementation of stack using 'Linked List'
case 4:
display();
break;
case 5:
exit(0);
}
}while(op<5);
getch();
}
void create()
{
int n,i;
s=NULL;
printf("Enter the no of nodes to be created\n");
scanf("%d",&n);
newnode=(struct node*)malloc(sizeof(struct node));
printf("Enter the data\t");
scanf("%d",&newnode->data);
newnode->next=NULL;
top=newnode;
s=newnode;
for(i=2;i<=n;i++)
{
newnode=(struct node*)malloc(sizeof(struct node));
printf("Enter the data\t");
scanf("%d",&newnode->data);
newnode->next=top;
s=newnode;
top=newnode;
}}
void display()
{ top=s;
while(top!=NULL)
{
printf("%d->",top->data);
top=top->next;
}
printf("NULL\n");
}
void push()
{ top=s;
newnode=(struct node*)malloc(sizeof(struct node));
printf("Enter the data\t");
scanf("%d",&newnode->data);
newnode->next=top;
top=newnode;
s=newnode;
display();
}
void pop()
{
top=s;
if(top==NULL)
printf("Empty stack\n\n");
else
{
temp=top;
printf("Deleted element is \t %d\n\n",top->data);
s=top->next;
free(temp);
display();
}}
Output
### Linked List Implementation of STACK Operations ###
Press 1-create
2-Push
3-Pop
4-Display
5-Exit
Your option ? 1
Enter the no of nodes to be created5
Enter the data 10
Enter the data20
Enter the data30
Enter the data40
Enter the data50
### Linked List Implementation of STACK Operations ###
Press 1-create
2-Push
3-Pop
4-Display
5-Exit
Your option ? 4
50->40->30->20->10->NULL
### Linked List Implementation of STACK Operations ###
Press 1-create
2-Push
3-Pop
4-Display
5-Exit
Your option ?2
Enter the data60
Your option ? 4
60->50->40->30->20->10->NULL
Your option ?2
Enter the data70
Your option ? 4
70->60->50->40->30->20->10->NULL
Your option ?3
Deleted element is70
Your option ? 4
50->40->30->20->10->NULL
Applications of Stack
INFIX:
The arithmetic operator appears between the two operands to which it is being
applied.
POSTFIX:
The arithmetic operator appears directly after the two operands to which it applies.
Also called reverse polish notation.
PREFIX:
The arithmetic operator is placed before the two operands to which it applies. Also
called polish notation.
Read the infix expression one character at a time until it encounters the delimiter “#”
Step 2: If the character is an operator, push it onto the stack. If the stack operator has a higher or
equal priority than input operator then pop that operator from the stack and place it onto the
output.
Step 3:If the character is left parenthesis, push it onto the stack
Step 4:If the character is a right parenthesis, pop all the operators from the stack till it encounters
left parenthesis, discard both the parenthesis in the output.
E.g. Consider the following Infix expression: - A*B+(C-D/E)#
A A
*
A
B
+ AB
*
+ AB*
( AB*
(
+
Read char Stack Output
C AB*C
(
+
- AB*C
- (
+
- AB*CD
D (
+
AB*CD
/ /
-
(
+
AB*CDE
E /
-
(
+
AB*CDE/-
) /
-
(
+
Read char Stack Output
AB*CDE/-+
Read the postfix expression one character at a time until it encounters the delimiter „#‟
Step 1: If the character is an operand, push its associated value onto the stack.
Step 2: If the character is an operator, POP two values from the stack, apply the operator to
them and push the result onto the stack.
Operand Value
A 2
B 3
C 4
D 4
E 2
A 2
3
B
2
Char Read Stack
* 6
4
C 6
4
D 4
6
2
/ 4
6
2
- 6
+ 8
OUTPUT = 8
(
(
a a
(
+ a
+
(
b ab
+
(
) ab+
* ab+
c ab+c
/ ab+c*
d ab+c*d
ab+c*d/
+
21
e ab+c*d/e
/ ab+c*d/e
/
+
f ab+c*d/ef
/
+
# ab+c*d/ef/+
Operand Value
a 1
b 2
c 4
d 2
e 6
f 3
Char Read Stack
a 1
2
b
1
+ 3
4
c 3
* 12
2
d 12
/ 6
6
e 6
3
F 6
6
2
/ 6
+ 8
Output = 8
Infix to Postfix Conversion Output
#define SIZE 50 /* Size of Stack */
#include <ctype.h>
char s[SIZE];
int top=-1; /* Global declarations */
char pop()
{
return(s[top--]);
} (a+b)-(c-d)
Void main()
{ /* Main Program */
char infx[50],pofx[50],ch,elem;
int i=0,k=0;
printf("\nRead the Infix Expression ? ");
scanf("%s",infx);
push('#');
while( (ch=infx[i++]) != '\0')
{
if( ch == '(') push(ch);
else
if(isalnum(ch)) pofx[k++]=ch;
else
if( ch == ')')
{
while( s[top] != '(')
pofx[k++]=pop();
elem=pop(); /* Remove */
}
else
{ /* Operator */
while( pr(s[top]) >= pr(ch) )
pofx[k++]=pop();
push(ch);
}
}
while( s[top] != '#') /* Pop from stack
till empty
pofx[k++]=pop();
pofx[k]='\0'; /* Make pofx as valid
string */
printf("\n\nGiven Infix Expn: %s Postfix
Expn: %s\n",infx,pofx);
}
Towers of Hanoi
Towers of Hanoi can be easily implemented using recursion. Objective of the problem is
moving a collection of N disks of decreasing size from one pillar to another pillar. The movement
of the disk is restricted by the following rules.
Rule 2 : No larger disk could ever reside on a pillar on top of a smaller disk.
Rule 3 : A 3rd pillar could be used as an intermediate to store one or more disks, while they
A B C
Step 2. If N = 2, move the 1st disk from A to B. Then move the 2nd disk from A to C, The move
the 1st disk from B to C.
Step 3. If N = 3, Repeat the step (2) to more the first 2 disks from A to B using C as intermediate.
Then the 3rd disk is moved from A to C. Then repeat the step (2) to move 2 disks from B to C using
A as intermediate.
In general, to move N disks. Apply the recursive technique to move N - 1 disks from A to B using
C as an intermediate. Then move the Nth disk from A to C. Then again apply the recursive technique
to move N - 1 disks from B to C using A as an intermediate
O(N)=O(N-1)+1+O(N-1) =2N-1
Function Calls
When a call is made to a new function all the variables local to the calling routine need to
be saved, otherwise the new function will overwrite the calling routine variables. Similarly the
current location address in the routine must be saved so that the new function knows where to go
after it is completed.
Main() Balance()
balance()
Recursive Function to Find Factorial
int fact(int n)
{
int S;
if(n==1)
return(1);
else
S = n * fact( n – 1 );
return(S)
}
Compilers check the programs for errors, a lack of one symbol will cause an error.
A Program that checks whether everything is balanced.
Every right parenthesis should have its left parenthesis.
Check for balancing the parenthesis brackets braces and ignore any other character.
((B*B)-{4*A*C}/[2*A]) #
( (
(
)
(
{ {
(
}
(
[ [
(
]
(
Empty stack, hence the symbols the balanced in the given expression.
Example for unbalanced symbols:
QUEUES:
Queue is a Linear Data Structure that follows First in First out (FIFO) principle.
Insertion of element is done at one end of the Queue called “Rear “end of the Queue.
Deletion of element is done at other end of the Queue called “Front “end of the Queue.
Example: - Waiting line in the ticket counter.
Front End
RearEnd
QUEUE Q
Deletion
Insertion
Queue Model
Front Pointer:-
Rear Pointer:-
Front (F) = - 1
Rear (R) = - 1
Operations on Queue
1. EnQueue
2. DeQueue
(i) EnQueue operation:-
It is the process of inserting a new element at the rear end of the Queue.
For every EnQueue operation
o Check for Full Queue
o If the Queue is full, Insertion is not possible.
o Otherwise, increment the rear end by 1 and then insert the element in the rear end
of the Queue.
It is the process of deleting the element from the front end of the queue.
For every DeQueue operation
o Check for Empty queue
o If the Queue is Empty, Deletion is not possible.
o Otherwise, delete the first element inserted into the queue and then increment the
front by 1.
Queue Overflow
Queue Underflow
An Attempt to insert an element X at the Rear end of the Queue when the
Queue is full is said to be Queue overflow.
For every Enqueue operation, we need to check this condition.
(ii) Queue Underflow:
An Attempt to delete an element from the Front end of the Queue when the
Queue is empty is said to be Queue underflow.
For every DeQueue operation, we need to check this condition.
Implementation of Queue
return ( 1 );
As we keep inserting the new elements at the Rear end of the Queue, the Queue becomes
full.
When the Queue is Full, Rear reaches its maximum Arraysize.
For every Enqueue Operation, we need to check for full Queue condition.
if ( Rear = = ArraySize - 1 )
return ( 1 );
}
(iii) Enqueue Operation
It is the process of inserting a new element at the Rear end of the Queue.
It takes two parameters, Enqueue(X, Q). The elements X to be inserted at the Rear end of
the Queue Q.
Before inserting a new Element into the Queue, check for Full Queue.
If the Queue is already Full, Insertion is not possible.
Otherwise, Increment the Rear pointer by 1 and then insert the element X at the Rear end
of the Queue.
If the Queue is Empty, Increment both Front and Rear pointer by 1 and then insert the
element X at the Rear end of the Queue.
#include<stdio.h>
#include<conio.h>
#define SIZE 5
int front = - 1;
int rear = - 1;
int q[SIZE];
void insert( );
void del( );
void display( );
void main( )
{
int choice;
clrscr( );
do
{
printf("\t Menu");
printf("\n 1. Insert");
printf("\n 2. Delete");
printf("\n 3. Display ");
printf("\n 4. Exit");
}while(choice != 4);}
void insert( )
{
int no;
printf("\n Enter No.:");
scanf("%d", &no);
void del( )
{
if(front = = - 1)
{
printf("\n Queue Underflow");
return;
}
else
{
printf("\n Deleted Item:-->%d\n", q[front]);
}
if(front = = rear)
{ output
Front = - 1;
Rear = - 1;
}
else
{
Front = front + 1;
}}
void display( )
{
int i;
if( front = = - 1)
{
printf("\nQueue is empty... ");
return;
}
for(i = front; i<=rear; i++)
printf("\t%d",q[i]);}
Linked List Implementation of Queue
Header
10 20 30 40 NULL
Front Rear
struct node;
typedef struct node * Queue;
typedef struct node * position;
int IsEmpty (Queue Q);
Queue CreateQueue (void);
void MakeEmpty (Queue Q);
void Enqueue (int X, Queue Q);
void Dequeue (Queue Q);
struct node
{
int data ;
position next;
}* Front = NULL, *Rear = NULL;
(i) Queue Empty Operation:
Initially Queue is Empty.
With Linked List implementation, Empty Queue is represented as S -> next = NULL.
It is necessary to check for Empty Queue before deleting the front element in the Queue.
It is the process of inserting a new element at the Rear end of the Queue.
It takes two parameters, EnQueue ( int X , Queue Q ). The elements X to be inserted into
the Queue Q.
Using malloc ( ) function allocate memory for the newnode to be inserted into the Queue.
If the Queue is Empty, the newnode to be inserted will become first and last node in the
list. Hence Front and Rear points to the newnode.
Otherwise insert the newnode in the Rear -> next and update the Rear pointer.
Header NULL
Q
Before Insertion
Front Rear
It takes one parameter, Dequeue ( Queue Q ). Always element in the front (i.e) element pointed
by Q -> next is deleted always.
Element to be deleted is made “temp”.
If the Queue is Empty, then deletion is not possible.
If the Queue has only one element, then the element is deleted and Front and Rear pointer is
made NULL to represent Empty Queue.
Otherwise, Front element is deleted and the Front pointer is made to point to next node in the list.
The free ( ) function informs the compiler that the address that temp is pointing to, is unchanged
but the data present in that address is now undefined.
Header
20 30 40 NULL
Front Rear
www.padeepz.net
Routine to DeQueue an Element from the Queue
struct node
{
int data;
position next;
};
void main()
{
int choice;
clrscr();
do
{
printf("1.Enqueue\n2.Dequeue\n3.display\n4.exit\n");
printf("Enter your choice\n\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
enqueue();
break;
case 2:
dequeue();
break;
case 3:
display();
break;
case 4:
exit(0);
}
}
while(choice<5);
}
void enqueue()
{
newnode=(struct node*)malloc(sizeof(struct node));
printf("\n Enter the data to be enqueued\n");
scanf("%d",&newnode->data);
newnode->next=NULL;
if(rear==NULL)
front=rear=newnode;
else {
rear->next=newnode;
rear=newnode;
}
display();
}
void dequeue()
{
if(front==NULL)
printf("\nEmpty queue!!!!! Deletion not possible\n");
else if(front==rear)
{
printf("\nFront element %d is deleted from queue!!!! now queue is
empty!!!! no more deletion possible!!!!\n",front->data);
front=rear=NULL;
}
else
{
temp=front;
front=front->next;
printf("\nFront element %d is deleted from queue!!!!\n",temp->data);
free(temp);
}
display();
}
void display()
{
p=front;
while(p!=NULL)
{
printf("%d -> ",p->data);
p=p->next;
}
printf("Null\n");
}
Output
Applications of Queue
1. Serving requests on a single shared resource, like a printer, CPU task scheduling etc.
2. In real life, Call Center phone systems will use Queues, to hold people calling them in an
order, until a service representative is free.
3. Handling of interrupts in real-time systems. The interrupts are handled in the same order
as they arrive, First come first served.
4. Batch processing in operating system.
5. Job scheduling Algorithms like Round Robin Algorithm uses Queue.
With the array implementation of Queue, the element can be deleted logically only by
moving Front = Front + 1.
Here the Queue space is not utilized fully.
In Circular Queue, the insertion of a new element is performed at the very first location of the
queue if the last location of the queue is full, in which the first element comes just after the last
element.
A circular queue is an abstract data type that contains a collection of data which allows
addition of data at the end of the queue and removal of data at the beginning of the
queue.
Circular queues have a fixed size.
Circular queue follows FIFO principle.
Queue items are added at the rear end and the items are deleted at front end of the circular
queue
Here the Queue space is utilized fully by inserting the element at the Front end if the rear
end is full.
It is same as Linear Queue EnQueue Operation (i.e) Inserting the element at the Rear end.
First check for full Queue.
If the circular queue is full, then insertion is not possible.
Otherwise check for the rear end.
If the Rear end is full, the elements start getting inserted from the Front end.
F
Circular Queue DeQueue Operation
It is same as Linear Queue DeQueue operation (i.e) deleting the front element.
First check for Empty Queue.
If the Circular Queue is empty, then deletion is not possible.
If the Circular Queue has only one element, then the element is deleted and Front and Rear
pointer is initialized to - 1 to represent Empty Queue.
Otherwise, Front element is deleted and the Front pointer is made to point to next element in the
Circular Queue.
F, R
F= -1,R= --1
void insert()
{
int x;
if((front==0&&rear==max-1)||(front>0&&rear==front-1))
printf("Queue is overflow\n");
else
{
printf("Enter element to be insert:");
scanf("%d",&x);
if(rear==max-1&&front>0)
{ rear=0;
q[rear]=x;
}
else
{
if((front==0&&rear==-1)||(rear!=front-1))
q[++rear]=x;
} }}
void delet()
{
int a;
if((front==0)&&(rear==-1))
printf("Queue is underflow\n");
if(front==rear)
{
a=q[front];
rear=-1;
front=0;
}
else if(front==max-1)
{
a=q[front];
front=0;
}
else
a=q[front++];
printf("Deleted element is:%d\n",a);
}
void display()
{
int i,j; if(front==0&&rear==-1)
printf("Queue is underflow\n");
if(front>rear) {
for(i=0;i<=rear;i++)
printf("\t%d",q[i]);
for(j=front;j<=max-1;j++)
printf("\t%d",q[j]);
printf("\nrear is at %d\n",q[rear]);
printf("\nfront is at %d\n",q[front]); }
else
{
for(i=front;i<=rear;i++)
printf("\t%d",q[i]); printf("\nrear
is at %d\n",q[rear]); printf("\nfront
is at %d\n",q[front]);
}
printf("\n");
}
OUTPUT
In DEQUE, insertion and deletion operations are performed at both ends of the Queue.
Insertion
Deletion
Deletion
Front Rear
(ii) Output Restricted DEQUE
Here insertion is allowed at both ends and deletion is allowed at one end.
Insertion
Insertion
Deletion
Front Rear
Operations on DEQUE
Four cases for inserting and deleting the elements in DEQUE are