Professional Documents
Culture Documents
Stack: - Stack is a linear data structure in which a data item is inserted and deleted at one
end. A stack is called a Last in First out (LIFO) structure because the data item that is last
inserted into the stack and is the first data item to be deleted from the stack.
In general, writing a value to the stack is called as a push operation whereas reading a value from
it is called as a pop operation.
Here in stacks a variable top is used to represent the top of the stack. Initially top=-1. For every
insertion, i.e. push, operation the top is increased by one and element is stored in stack and for
every deletion, i.e. pop, operation the top element is deleted and decremented by one.
EXAMPLE:
Push A A :A is pushed
Push B AB :B is pushed
Pop A :B is popped(deleted)
Push C AC :C is inserted
Pop AC :D is deleted
Pop A :C is deleted
The above example shows the working of stacks for moving an element into stack and deleting
an element from stack.
DS in C NEC, CSE Dept. Page 1
UNIT 3 Stacks and Queues
Stacks are extensively used in computer applications. For example, when one c function calls
another function, and passes some parameters, these parameters are passed using the stack.
The stacks can be represented using array. The variable top indicates the current top of the stack
and it moves up and down depending on whether new items are added to the stack (or) existing
item is removed.
push(item)
item: item to be inserted on to the stack
begin
if top=(MAX-1) then /* where MAX is the size of stack*/
write stack is full
otherwise
top=top+1
stack[top]=item
end of if
end of push
EXAMPLE:
returntype pop()
begin
initialize item;
DS in C NEC, CSE Dept. Page 2
UNIT 3 Stacks and Queues
if top=-1 then
write stack is empty
otherwise
item=stack[top]
top=top-1
end of if
end of pop
EXAMPLE:
returntype stacktop()
begin
if top=-1
write stack is empty
otherwise
return stack[top]
end of if
end of stacktop
display()
begin
initialize i
if top=-1
write stack is empty
otherwise
for i=top to 0
print stack[i]
end of if
end of display
#include<stdio.h>
#include<conio.h>
#include<process.h>
int stack[100],top=-1,
void push(int);
int pop();
int stacktop();
void display();
void main()
{
int item,ch;
clrscr();
while(1)
{
clrscr();
printf("stackoperations\n");
printf("1.push\n2.pop\n3.stacktop\n4.display\n5.exit\n");
printf("enter your choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1:printf("enter an element");
scanf("%d",&item);
push(item);
getch();
break;
case 2:
item=pop();
if(item==-1)
printf("stack is empty");
else
printf("element deleted is %d\n ",item);
getch();
break;
case 3:
item=stacktop();
DS in C NEC, CSE Dept. Page 4
UNIT 3 Stacks and Queues
if(item==-1)
printf("stack is empty\n")
else
printf("topelement is %d\n",item);
getch();
break;
case 4:
display();
getch();
break;
default:getch();
exit(0);
}
}
}
void push(int item)
{
if(top==99)
printf("stack is full");
else
{
top=top+1;
stack[top]=item;
}
}
int pop()
{
int item;
if(top==-1)
return -1;
else
{
item=stack[top];
top=-1;
return item;
}}
int stacktop()
{
if(top==-1)
return -1;
else
return stack[top];
}
void display()
{
int i;
DS in C NEC, CSE Dept. Page 5
UNIT 3 Stacks and Queues
if(top==-1)
printf("stack is empty");
else
{
for(i=top;i>=0;i--)
printf("%d\t",stack[i]);
printf("\n");
}
}
Applications of stack:
The stack usually works by inserting a new element into top of the stack and deleting the element
from the top of the stack.
The elements of stack are displayed from top to bottom of stack, i.e. which displays the element
reverse order based on insertion.
To understand this, imagine a pile of books usually, we pick up the topmost book from the pile.
The elements in the list are displayed in reverse order.
display()
begin
initialize i
if top=-1
write stack is empty
otherwise
for i=top to 0
ptint stack[i]
end of if
end of display
Factorial calculation:
int factorial(int n)
{
int x,y;
if(n==0||n==1)
{
x=1;
return 1;
}
else
{
x=n-1;
y=factorial(x);
return y*n;
}
}
The function does not lead to an endless series of calls to itself because of the base case. The
series of calls made by procedure factorial () to itself based on the value of n, this can be viewed
as factorial () calling itself as many times as itself with varying values of n. A procedure call
would have a normal termination only when either the base case is executed (or) the recursive
case has successfully ended.
During the execution, to keep track of the calls made to it and to record the status of the
parameters at the time of the call, a stack data structure is used.
When the procedure factorial (5) is initiated and executed x obtains the value 4 and the control
flow moves to y=factorial (4). This initiates the next call to the procedure as factorial (4).
Observe that 1st call, factorial (5), has not finished its execution when the next call factorial (4),
to the procedure has been issued. Therefore, there is a need to store preceding calls.
Every new procedure call pushes the current values of the parameters involved into the stack,
thereby preserving the values used by the earlier calls
The values of 3 parameters n, x, y are keep track of in the stack data structure along with the
return values and return address.
The following figure illustrates the various snap shots of the stack during the execution of
factorial (5)
Factorial (5): causes all the parameters, local variables, return values and return address of
factorial (5) will be stored in stack. [Stack elements during Factorial (5)]
n=5 x=4 y= factorial (4)
Factorial (4): causes all the parameters, local variables, return values and return address of
factorial (4) will be stored in stack. [Stack elements during Factorial (4)]
n=4 x=3 y= factorial (3)
n=5 x=4 y= factorial (4)
Factorial (1): During this function call return statement has encountered which causes the stack
to deallocate the function variables and control shifts to previous function call i.e. factorial (1) by
returning a value with the help of return address. [Stack elements during Factorial (1)]
n=1 x=1 return 1;
n=2 x=1 y= factorial (1)
n=3 x=2 y= factorial (2)
n=4 x=3 y= factorial (3)
n=5 x=4 y= factorial (4)
120
Figure: stack usage when a function factorial (5) has been called.
Now the function factorial (5) has returned a value 120 to previous function calling location.
Stacks are used in this manner when a function has been called.
2. For each character in input string-if input string is an operand append to the output
Else
If stack is empty (or) the operator has higher priority than the operator on the top of the stack (or)
the top of the stack is opening parenthesis
Then
Push the operator onto the stack
Else
Pop the operator from the stack and append to the output.
3. If the input string is a closing parenthesis pop operator from the stack and append the
operators to the output until an opening parenthesis is encountered. Pop the opening parenthesis
from the stack and discard it.
4. If the end of the input string is encountered then iterate the loop until the stack is not empty.
Pop the stack and append the remaining input string to the output.
EXAMPLE: A*B/(C-D)+E*(F-G)
A empty A
* * A
B * AB
/ / AB*
( /( AB*
C /( AB*C
- /(- AB*C
D /(- AB*CD
) / AB*CD-
+ + AB*CD-/
E + AB*CD-/E
* +* AB*CD-/E
( +*( AB*CD-/E
F +*( AB*CD-/EF
- +*(- AB*CD-/EF
G +*(- AB*CD-/EFG
) +* AB*CD-/EFG-
Program:-
#include<stdio.h>
#include<conio.h>
#include<string.h>
char stack[20];
int top=-1;
char pop();
void push(char item);
int precedence(char symbol)
{
switch(symbol)
{
case '+':
case '-':return 2;
case '*':
case '/':
case '%':return 3;
case '(':
case ')':return 1;
}
return 0;
}
int isoperator(char symbol)
{
switch(symbol)
{
case '+':
case '-':
case '*':
case '/':
case '%':
case '(':
case ')': return 1;
default: return 0;
}
}
void infixtopostfix(char input[],char output[])
{
int i,symbol,j=0;
stack[++top]='#';
for(i=0;i<strlen(input);i++)
{
symbol=input[i];
if(isoperator(symbol)==0)
{
output[j]=symbol;
j++;
DS in C NEC, CSE Dept. Page 11
UNIT 3 Stacks and Queues
}
else
{
if(symbol=='(')
push(symbol);
else
if(symbol==')')
{
while(stack[top]!='(')
{
output[j]=pop();
j++;
}
pop();
}
else
{
if(precedence(symbol)>precedence(stack[top])
push(symbol);
else
{
while(precendence(symbol)<=precendence(stack[top])
{
output[j]=pop();
j++;
}
push(symbol);
}
}
}
}
while(stack[top]!='#')
{
output[j]=pop();
j++;
}
output[j]='\0';
}
void main() string is:\t");
{ puts(output);
char input[20],output[20]; getch();
clrscr(); }
printf("enter the infix string\n");
gets(input); void push(char item)
infixtopostfix(input,output); {
printf("the corresponding postfix stack[++top]=item;
} return stack[top--];
}
char pop()
{
The stacks are used in evaluation of arithmetic expression. The stacks will
evaluate the infix expression by converting into postfix expression.
Result=2 for the above example the result is 2. Therefore, (6+8) / (9-2) = 2
Program:-
#include<stdio.h>
#include<conio.h>
DS in C NEC, CSE Dept. Page 13
UNIT 3 Stacks and Queues
#include<string.h>
int stack[20], top=-1;
int pop();
void main()
{
int i=0,x,term1,term2;
char str[20];
clrscr();
printf("enter the postfix expression");
gets(str);
while(str[i]='\0')
{
if(str[i]>='0'&&str[i]<='9')
{
x=str[i]-'0';
push(x);
}
else
{
term1=pop();
term2=pop();
switch(str[i])
{
case '+':push(term2+term1);
break;
case '-': push(term2-term1);
break;
case '*':push(term2*term1);
break;
case '/':push(term2/term1);
break;
case '%':push(term2%term1);
break;
default: exit(0);
}
}
}
printf("the value of postfix expression is %d",pop());
getch();
}
void push(int x)
{
if(top==9)
{
printf("stack is full");
}
DS in C NEC, CSE Dept. Page 14
UNIT 3 Stacks and Queues
else
{
top++;
stack[top]=x;
}
}
int pop()
{
int item;
if(top==-1)
return -1;
item=stack[top];
top--;
return item;
}
Queues:-
Queue is a linear data structure that is accessed in the order of First in First
out (FIFO), i.e. the 1st item inserted in a queue is also the first one to be
accessed, and the last one to be inserted is also the last one to be accessed.
Here all insertions are made at one end of the last known as rear (or) tail of
the queue and all deletions are made at the other end of queues known as
front (or) head of the queue.
In the above example, the insert operation adds a new item to queue and
the delete operation removes an item from stack .The item which is
inserted into queue at the first is also the first item to be removed from the
queue.
The variables front and rear keeps track of the front and rear ends in a
queue to facilitate execution of insertion and deletion operations
DS in C NEC, CSE Dept. Page 16
UNIT 3 Stacks and Queues
respectively.
Here front and rear are initialized to -1 and for every insert operation rear
variable is increased by one and front variable is increased by one for every
deletion operation from queue.
insert(item)
item:item to be inserted on to queue
begin
if(rear=MAX-1) then /*where MAX is Queue size
write queue is full
otherwise
rear=rear+1;
q[rear]=item;
Here in this algorithm the condition is checked whether the queue is full or
not. If possible the element is added or inserted into queue by increasing
the rear variable.
delete()
begin
initialize item
if front=rear then
write queue is empty
otherwise
front=front+1;
item=q[front];
return item;
end of if
end of delete
Here in this algorithm the condition front=rear is checked for the emptiness
of the queue. If the queue is not empty, front is increased by one and the
element pointing to front is removed from queue.
EXAMPLE:-
In the above example the insertion operation was unsuccessful for inserting
the ff element in to queue even the memory is available, since the rear
variable pointing MAXIMIUM position of queue. This is a major
limitation when a queue full condition is involved it does not necessary to
imply that the queue is 'physically full. This leads to the limitation of
rejecting insertions despite the space available. This limitation can be
eliminated using circular queues.
#include<stdio.h>
#include<conio.h>
#include<process.h>
int queue[20], front=-1,rear=-1;
int delete();
void insert(int);
void display();
void main()
{
int ch,item;
clrscr();
while(1)
{
clrscr();
printf("queue operations\n");
printf("1.insert\n2.delete\n3.display\n4.exit\n");
printf("enter your choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1:printf("enter an element");
scanf("%d",&item);
insert(item);
getch();
break;
case 2:
item=delete();
if(item==-1)
printf("queue is empty");
else
printf("element deleted is %d\n ",item);
getch();
break;
case 3:
display();
getch();
break;
default:
exit(0);
}
}
}
{
if(rear==19)
printf("queue is full");
else
{
rear=rear+1;
queue[rear]=item;
}
}
int delete()
{
int item;
if(front==rear)
return -1;
else
{
front=front+1;
item=queue[front];
return item;
}
}
void display()
{
int i;
if(front==rear)
printf("queue is empty");
else
{
for(i=front+1;i<=rear;i++)
printf("%d\t",queue [i]);
printf("\n");
}
}
This method makes sure that newly entered element is always at the first
position of the stack 1. So the dequeue operation just removes the top
elements from stack 1 to stack 2 and put the first element in the stack 1 and
pop the elements from stack 2 to stack 1 is used.
Example:
insert 1 2 3
delete
delete
insert 4
insert 3 3 12
321
delete 3
insert 4 4 3
43
Here in this example the element 1 is inserted first & the same element is
deleted first so the approach is FIFO which is the property of queues.
In this method the enqueue operation works by inserting the new element
in the stack 1 by using top variable. Dequeue operation works by deleting
the elements from stack 2. If stack 2 is empty then all the elements are
moved from stack 1 to stack 2 and finally top of stack 2 is returned.
Enqueue:-
Dequeue:
Example:
insert 1 2 3
delete
delete
insert 4
Here, in this method queue approach is followed and more, the number of
operations is less compared to method 1.
#include<stdio.h>
#include<conio.h>
int top1=-1,top2=-1;
int stack1[20],stack2[20];
void push1(int item);
DS in C NEC, CSE Dept. Page 23
UNIT 3 Stacks and Queues
void push2();
int pop1();
int pop2();
void main()
{
int i,ch,item;
while(1)
{
clrscr();
printf("1.Insert\n2.Delete\n");
printf("Enter your choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: printf("Enter the new element\n");
scanf("%d",&item);
push1(item); getch(); break;
case 2: item=pop2();
if(item==-1)
printf("Empty\n");
else
printf("Element Deleted is %d\n",item);
getch(); break;
default: exit(0);
} /*switch*/
} /*while*/
} /*main*/
void push1(int item)
{
if (top1==19)
printf("full\n");
else
{
top1=top1+1;
stack1[top1]=item;
}
}
int pop1()
{
int item;
if(top1>=0)
item=stack1[top1--];
return item;
}
void push2()
{
DS in C NEC, CSE Dept. Page 24
UNIT 3 Stacks and Queues
if(top1==-1)
printf("empty\n");
else
{
while(top1>=0) {
top2=top2+1;
stack2[top2]=pop1();
}}
}
int pop2()
{
int item;
if(top2<0&&top1<0)
return -1;
if(top2==-1)
push2();
if(top2>=0)
{
top2=top2-1;
item=stack 2[top2];
}
return item;}
Priority Queue:
The figure(c) represents the deletion of the element from priority queue in
this queue; the 1st element of queue is deleted.
Ex: Let queue (priority) with jobs are J1(1) J2(1) J3(0) . Here J1 is job with
priority 1, J2 with 1 priority.
Operations: J4(2) arrives , J5(2) arrives , execute job , execute job, execute
job.
1. J4 (2) arrives
High Priority (2)
Job queue
2. J5 (2) arrives
High Priority (2)
Job queue
3. Executes Job
High Priority (2)
Job queue
J4
(2) is Deleted
Medium Priority (1)
Job Queue
4. Execute Job
High Priority (2)
Job queue
J5(2)
is deleted
Medium Priority (1)
Job Queue
5. Execute Job
High Priority (2)
Job queue (EMPTY)
J1(1)
is deleted Medium Priority (1)
Job Queue
The above example shows the working of priority queue for cluster of
queues and priority queue.
front pointing to the element at the head of the queue and rear pointing to
the element at the tail end of the queue.
The Circular queues are using the memory more efficiently than the linear
queues.
In the above example, memory is used efficiently than linear queue data
structure.
rear=19;
else
rear = rear-1;
}
else
CQ[rear]=item;
}
}
void delete()
{
int item;
if(front==-1&&rear==-1)
printf("CQ is empty\n");
else
if(front==rear)
{
printf(Deleted Element is %d\n,CQ[front]); front=rear=-1; }
else
{
item=CQ[front];
front=(front+1)%20;
printf("Element deleted is %d\n",item);
}
}
void display()
{
int i;
if(front==-1 && rear==-1)
printf("CQ is empty\n");
else
if(front==rear)
printf(Single Element in the queue is %d\n,CQ[front]);
else
{
printf(Circular Queue Elements are\n);
printf(%d\t,CQ[front]);
i=front;
while(i!=rear)
{
i=(i+1)%20;
printf("%d\t",CQ[i]);
}
} }
A deque is more general a stack (or) queue, if it follows the approach LIFO
(or) FIFO respectively. Here two ends are referred to as right end (or) left
end of a deque.
A deque can be of two types: Input restricted deque and output restricted
deque.
left =(left-1)%size
right =(right+1)%size
left =(left+1)%size
right =(right-1)%size
The contents of DEQ and that of Left and right are as given below.
DEQ: Left: 2 Right: 4
0 1 2 3 4 5
The Scheduler chooses the 1st process from the queue and assigns the CPU
to it. If the process does not finish its job, then that process will be added at
the rear end, if the process finishes its job in given time interval then it is
deleted from the queue. The CPU scheduler assigns the CPU to the next
process in the queue.