Printed Stack
Printed Stack
Chapter – 04 : “Stacks”
tacks”
STACKS
• A common model of a stack is plates in a marriage party. Fresh plates are “pushed”
onto the top and “popped” off the top.
• Some of you may eat biscuits. If you assume only one side of the cover is torn and
biscuits are taken off one by one. This is called popping and similarly, if you want to
preserve some biscuits for some time later, you will put them back into the pack
through the same torn end called pushing.
Whenever, a stack is created, the stack base remains fixed, as a new element is
added to the stack from the top, the top goes on increasing, conversely as the top most
element of the stack is removed the stack top is decrementing.
Static implementation
Dynamic implementation
As in static implementation, we have used arrays to store the elements that get
added to the stack. However, implemented as an array it suffers from the basic limitation
of array-that its size cannot be increased or decreased one it is declared. As a result, one
ends up reserving either too much space or too less space for an array and in turn for a
stack. This problem can be overcome if we implement a stack using a linked list. In case
of a linked list we shall push and pop nodes from one end of a linked list. Linked list
representation is commonly known as Dynamic implementation and uses pointers to
implement the stack type of data structure. The stack as linked list is represented as a
singly connected list. Each node in the linked list contains the data and a pointer that
gives location of the next node in the list. The node in the list is a structure as shown
below :
struct node
{
<data type> data;
node *link;
};
where <data type> indicates that the data can be of any type like int, float, char etc, and
link, is a pointer to the next node in the list. The pointer to the beginning of the list serves
the purpose of the top of the stack. Fig. (1) shows the linked list representation of a stack
Top
23
N stands for NULL
-16
11
10 N
ALGORITHMS FOR PUSH & POP FOR STATIC IMPLEMENTATION USING ARRAYS
Let STACK[MAXSIZE] is an array for implementing the stack, MAXSIZE represents the max.
size of array STACK. NUM is the element to be pushed in stack & TOP is the index number
of the element at the top of stack.
Step 1 : [Check for stack overflow ? ]
If TOP = MAXSIZE – 1, then :
Write : ‘Stack Overflow’ and return.
[End of If Structure]
Step 2 : Read NUM to be pushed in stack.
Step 3 : Set TOP = TOP + 1 [Increases TOP by 1]
Step 4 : Set STACK[TOP] = NUM [Inserts new number NUM in new TOP Position]
Step 5 : Exit
void push()
{
if(top==MAXSIZE-1)
{
printf("\n\nStack is full(Stack overflow)");
return;
}
int num;
printf("\n\nEnter the element to be pushed in stack : ");
scanf("%d",&num);
top++;
stack[top]=num;
}
(ii) Algorithm for deleting an item from the stack (POP)
Let STACK[MAXSIZE] is an array for implementing the stack where MAXSIZE represents the
max. size of array STACK. NUM is the element to be popped from stack & TOP is the index
number of the element at the top of stack.
Step 1 : [Check for stack underflow ? ]
If TOP = -1 : then
Write : ‘Stack underflow’ and return.
[End of If Structure]
Step 2 : Set NUM = STACK[TOP] [Assign Top element to NUM]
Step 3 : Write ‘Element popped from stack is : ‘,NUM.
Step 4 : Set TOP = TOP - 1 [Decreases TOP by 1]
Step 5 : Exit
void pop()
{
if(top== -1)
{
printf("\n\nStack is empty(Stack underflow)");
return;
}
int num;
num=stack[top];
printf("\n\nElement popped from stack : %d",num);
top--;
}
Program 1 : Static implementation of stacks using arrays
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define MAXSIZE 5
void push();
void pop();
void display();
int stack[MAXSIZE];
int top=-1;
void main()
{
clrscr();
int choice;
while(1)
{
clrscr();
printf("STATIC IMPLEMENTATION OF STACK");
printf("\n------------------------------");
printf("\n1. PUSH");
printf("\n2. POP");
printf("\n3. DISPLAY");
printf("\n4. EXIT");
printf("\n------------------------------");
printf("\n\nEnter your choice [1/2/3/4] : ");
scanf("%d",&choice);
switch(choice)
{
case 1 : push();
break;
case 2 : pop();
break;
case 3 : display();
break;
case 4 : exit(0);
default : printf("\n\nInvalid choice");
}
getch();
}
}
// Function for the operation push
void push()
{
int num;
if(top==MAXSIZE-1)
{
printf("\n\nStack is full(Stack overflow)");
return;
}
printf("\n\nEnter the element to be pushed in stack : ");
scanf("%d",&num);
top++;
stack[top]=num;
}
// Function for the operation pop
void pop()
{
int num;
if(top==-1)
{
printf("\n\nStack is empty(Stack underflow)");
return;
}
num=stack[top];
printf("\n\nElement popped from stack : %d",num);
top--;
}
ALGORITHMS FOR PUSH & POP FOR DYNAMIC IMPLEMENTATION USING POINTERS
Let PTR is the structure pointer which allocates memory for the new node & NUM is the
element to be pushed into stack, TOP represents the address of node at the top of the stack,
INFO represents the information part of the node and LINK represents the link or next pointer
pointing to the address of next node.
Step 1 : Allocate memory for the new node using PTR.
Step 2 : Read NUM to be pushed into stack.
Step 3 : Set PTR->INFO = NUM
Step 4 : Set PTR->LINK=TOP
Step 5 : Set TOP = PTR
Step 6 : Exit
Function for PUSH
void push()
{
struct stack *ptr;
int num;
ptr=(struct stack *)malloc(sizeof(struct stack));
printf("\nEnter the element to be pushed in stack : ");
scanf("%d",&num);
ptr->info=num;
ptr->link=top;
top=ptr;
}
Let PTR is the structure pointer which deallocates memory of the node at the top of stack &
NUM is the element to be popped from stack, TOP represents the address of node at the top
of the stack, INFO represents the information part of the node and LINK represents the link or
next pointer pointing to the address of next node.
Step 1 : [Check for Stack Underflow ?]
If TOP = NULL : then
Write ‘Stack Underflow’ & Return.
[End of If Structure]
Step 2 : Set PTR=TOP.
Step 3 : Set NUM=PTR->INFO
Step 4 : Write ‘Element popped from stack is : ‘,NUM
Step 5 : Set TOP=TOP->NEXT
Step 6 : Deallocate memory of the node at the top using PTR.
Step 5 : Exit
Function for POP
void pop()
{
if(top==NULL)
{
printf("\nStack is empty(Stack underflow).");
return;
}
struct stack *ptr;
int num;
ptr=top;
num=ptr->info;
printf("\nElement popped from stack : %d",num);
top=top->link;
free(ptr);
}
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct stack
{
int info;
struct stack *link;
}*top=NULL;
void push();
void pop();
void display();
void main()
{
int choice;
while(1)
{
clrscr();
printf("DYNAMIC IMPLEMENTATION OF STACKS");
printf("\n--------------------------------");
printf("\n1. PUSH");
printf("\n2. POP");
printf("\n3. DISPLAY");
printf("\n4. EXIT");
printf("\n--------------------------------");
printf("\nEnter your choice [1/2/3/4] : ");
scanf("%d",&choice);
switch(choice)
{
case 1 : push();
break;
case 2 : pop();
break;
case 3 : display();
break;
case 4 : exit(0);
default: printf("\nInvalid choice.");
}
getch();
}
}
POLISH-NOTATIONS
The place where stacks are frequently used is in evaluation of arithmetic expression. An
arithmetic expression consists of operands and operators. The operands can be numeric values
or numeric variables. The operators used is an arithmetic expression represent the operations
like addition, subtraction, multiplication, division and exponentation.
When higher level programming languages came into existence one of the major hurdles
faced by the computer scientists was to generate machine language instructions that would
properly evaluate any arithmetic expression. To convert a complex assignment statement such as
X=A/B+C*D–F*G/Q
into a correct instruction sequence was a difficult task. To fix the order of evaluation of an
expression each language assigns to each operator a priority.
A polish mathematician suggested a notation called Polish notation, which gives two
alternatives to represent an arithmetic expression. The notations are prefix and postfix notations.
The fundamental property of Polish notation is that the order in which the operations are to be
performed is completely determined by the positions of the operators and operands in the
expression. Hence parenthesis are not required while writing expressions in Polish notation. The
Two types of polish notations are given below :
1. Prefix notation
2. Postfix notation
Prefix notation :
The prefix notation is a notation in which the operator is written before the operands. For
example,
+ AB
As the operator ‘+’ is written before the operands A and B, this notation is called prefix
notation (pre means before).
Postfix notation :
The postfix notation is a notation in which the operator is written after the operands. For
example,
AB +
As the operator ‘+’ is written after the operands A and B, this notation is called postfix
notation (post means after).
Infix notation :
The infix notation is what we come across in our general mathematics, where the operator
is written in-between the operands. For example : The expression to add two numbers A and B is
written in infix notation as :
A+B
Note that the operator ‘+’ is written in-between the operands A and B. The reason why this
notation is called infix, is the place of operator in the expression.
NOTATION CONVERSIONS
Let an expression A + B * C is given, which is in infix notation. To calculate this expression
for values 4, 3, 7 for A, B, C respectively, we must follow certain rule (called BODMAS in general
mathematics) in order to have right result. For example,
A + B * C = 4 + 3 * 7 = 7 * 7 = 49
This result is not right because the multiplication is to be done before addition because it has
higher precedence over addition. This means that for an expression to be calculated we must
have the knowledge of precedence of operators.
Operator precedence :
Exponential operator ^ Highest precedence
Multiplication/Division *, / Next precedence
Addition/Subtraction +, - Least precedence
Let P = (BC *)
A + (P – Q) * H
A + (PQ –) * H
Let O = (PQ –)
A+O *H
A + (OH *)
Let N = (OH *)
A+N
AN +
Algorithm :
Let Q is an arithmetic expression written in infix notation. This algorithm finds the
equivalent postfix expression P.