Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 35

STACKS

Stack:- Stack is a linear data structure, it is ordered to collection of homogeneous data


elements where the insertion and deletion operations occur at one end only called top at the stack.

i.e.

A stack is a data structure in which addition of new element or deletion of existing element
always takes place at the same end. This end is often known as top of stack.

Example:

This situation can be compared to a stack of plates in a cafeteria where every new plate
added to the stack is added at the top. similarly, every new plate taken off the stack is also from the
top of the stack.

The two changes that can be made to a stack are given special names:

 When an item is added to a stack, the operation is called push.

 When an item is removed from the stack the operation is called pop.

 Stack is also called as last-in-first-out (LIFO) list.

If the elements are added continuously to the stack it grows at the one end.

Pictorial representation of inserting elements at top of stack


On deletion of elements the stack shrink at the same end, as the elements at the top get removed.

Pictorial representation of deleting top elements from stack

A stack is generally implemented with two basic operations-push and pop.

The abstract data type for stack are push(), pop() and top() they are implemented in two ways.

1. Using an arrays

2. Using an linked lists.

Stack as an array:-

An array is used to store the ordered list of elements. Hence it is very easy to manage a
stack if we represent it using an array, however the problem with an array is that we are
required to declare the size of the array before using in it a program, i.e. size of array should
be fixed.
Though an array and stack are totally different data structures, an array can be used to
store the elements of a stack. We declare the array with a maximum size large enough to
manage a stack. As a result the stack can grow or shrink with in the space reserved for it.

Source code:-

#include<stdio.h>

#include<conio.h>

#include<alloc.h>

#define MAX 10

struct stack

int arr[MAX];

int top;

};

void push(struct stack *, int item);

void pop(struct stack *);

void main()

struct stack s;

int i;

clrscr();

s.top=-1;
push(&s,11);

push(&s,23);

push(&s,8);

push(&s,16);

push(&s,27);

push(&s,14);

push(&s,20);

push(&s,39);

push(&s,2);

push(&s,15);

printf("The elements in the stack after pushing:\n");

for(i=0;i<MAX;i++)

printf("%d\t",s.arr[i]);

push(&s,7);

pop(&s);

pop(&s);

pop(&s);

pop(&s);

pop(&s);

printf("\nThe elements in the stack after poping:\n");

for(i=0;i<=s.top;i++)

printf("%d\t",s.arr[i]);

getch();

}
//adds an element to the stack

void push(struct stack *s,int item)

if(s->top==MAX-1)

printf("\nstack is full");

return;

s->top++;

s->arr[s->top]=item;

// removes an element from the stack

void pop(struct stack *s)

int data,i;

if(s->top==-1)

printf("\nstack is empty");

return ;

data=s->arr[s->top];

s->arr[s->top]=NULL;
printf("\nitem popped: %d",data);

s->top--;

Stack as a linked list:

In the earlier we had used arrays to store the elements that get added to the stack,
however, when implemented as an array it suffers from the basic limitation of an array i.e
size cannot be increased or decreased once it is declared.

This problem can be overcome if we implement a stack using a linked list. In case of a
linked stack we shall push and pop nodes from one end of a linked list. The stack as linked
list is represented as a singly connected list.

The node in the list is a structure as shown below:

Struct node

<data type> data;

Struct node *link;

};

Linked list representation of stack:


Source code:-

#include<stdio.h>

#include<conio.h>

#include<alloc.h>

//structure containing data part and link part

struct node

int data;

struct node *link;

};

void push(struct node **,int);

int pop(struct node **);

void display(struct node *);

void main()

struct node *s=NULL;

int i;

clrscr();

push(&s,14);

push(&s,3);
push(&s,18);

push(&s,29);

push(&s,31);

push(&s,16);

display(s);

i=pop(&s);

printf("\n item popped:%d",i);

i=pop(&s);

printf("\n item popped:%d",i);

i=pop(&s);

printf("\n item popped:%d",i);

display(s);

getch();

// adds a new node to the stack as an linked list

void push(struct node **top,int item)

struct node *temp;

temp=malloc(sizeof(struct node));
temp->data=item;

temp->link=*top;

*top=temp;

//pops an element from the stack

int pop(struct node **top)

struct node *temp;

int item;

if(*top==NULL)

printf("\n stack is empty");

return NULL;

temp=*top;

item=temp->data;

*top=(*top)->link;

free(temp);

return item;

}
void display(struct node *s)

int c=0;

printf("\n");

while(s!=NULL)

printf("%d\t",s->data);

c++;

s=s->link;

printf("\nthe number of elements in linked list %d",c);

Applications of stack:-

 Parsing
 Calling function
 Recursive function
 Conversion of arithmetic expression
 Evaluation arithmetic expression

Polish notation:-

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 in an arithmetic expression represent the operations like
addition, subtraction, multiplication, division and exponentiation.

When higher level programming languages came in to 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 fix the order of evaluation of an expression each language assigns to each operator a
priority. Even after assigning priorities the computer failed to generate machine language instruction
that would properly evaluate the arithmetic expression like (A+B)*C.
“Then a polish mathematician Jan Lukasiewicz suggested a notation called Polish notation,
which gives two alternatives to represent an arithmetic expression.”

The two alternative notations are “prefix” and “postfix”. 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 expression. Hence parentheses are
not required while writing expressions in polish notation.

Notations of arithmetic expression:-


Priorities:-

Highest priority: Exponentiation ($)

Next highest priority: multiplication (*), division (/), modulo (%)

Lowest priority: addition (+) and subtraction (-)

Conversion of infix to postfix notation:- To convert the infix expression in to a post fix expression,
follow the below steps depending on the type of character scanned in infix.

Algorithm:-

a. Consider one infix expression S in a string format


b. If the character scanned happens to be a ‘space’ then that character is skipped
c. If the character scanned is a digit or an alphabet, it is added to the target(output)
d. If the character scanned is a open parenthesis then it is added to the stack by calling push()
function.
e. If the character scanned happens to be an operator, then firstly pop topmost element from
the stack. Then perform the following steps as per the precedence rule.
 If the popped element has higher or same priority as the character scanned, then
add the popped element to the target(output)
 If the popped element has lower priority than the character scanned, then push
back the popped element in to the stack and also add the character scanned is in to
stack by calling push().

f. If the character scanned happens to be an closing parenthesis, then pop the operators
present in the stack until encounter a open parentheses. Add the popped operators to the
output.
g. After completing the scanning of elements in infix expression, pop the all elements from the
stack one by one and add those popped elements to output.

Example :
((a+b)^c-(d*e)/f)

STACK OUTPUT

(( A

((+ AB

( AB+
(^ AB+

(^ AB+C

(- AB+C^

(-( AB+C^

(-( AB+C^D

(-(* AB+C^D

(-(* AB+C^DE

(- AB+C^DE*

(-/ AB+C^DE*F

AB+C^DE*F/-

Source code:-

#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<ctype.h>
#define MAX 50
struct infix
{
char target[MAX];
char stack[MAX];
char *s,*t;
int top;
};
void initinfix(struct infix *);
void setexpr(struct infix *, char *);
void push(struct infix *, char);
char pop(struct infix *);
void convert(struct infix *);
int priority(char);
void show(struct infix);
void main()
{
struct infix p;
char expr[MAX];
clrscr();
initinfix(&p);
printf("Enter an expression in infix form:\n");
gets(expr);
setexpr(&p,expr);
convert(&p);
printf("The postfix expression of given infix form:\n");
show(p);
getch();
}
//initializes structure elements
void initinfix(struct infix *p)
{
p->top=-1;
strcpy(p->target,"");
strcpy(p->stack,"");
p->t=p->target;
p->s="";
}
//sets s to point to given expr
void setexpr(struct infix *p,char *str)
{
p->s=str;
}
//adds an operator to the stack
void push(struct infix *p,char c)
{
if(p->top==MAX)
printf("stack is full\n");
else
{
p->top++;
p->stack[p->top]=c;
}
}
//pops an operator from the stack
char pop(struct infix *p)
{
if(p->top==-1)
{
printf("stack is empty\n");
return -1;
}
else
{
char item=p->stack[p->top];
p->top--;
return item;
}
}
//converts the given expr from infix to postfix form
void convert(struct infix *p)
{
char opr;
while(*(p->s))
{
if(*(p->s)==' '||*(p->s)=='\t')
{
p->s++;
continue;
}
while(isdigit(*(p->s))||isalpha(*(p->s)))
{
*(p->t)=*(p->s);
p->s++;
p->t++;
}
if(*(p->s)=='(')
{
push(p,*(p->s));
p->s++;
}
if(*(p->s)=='*'||*(p->s)=='+'||*(p->s)=='/'||*(p->s)=='%'||*(p->s)=='-'||*(p->s)=='$')
{
if(p->top!=-1)
{
opr=pop(p);
while(priority(opr)>=priority(*(p->s)))
{
*(p->t)=opr;
p->t++;
opr=pop(p);
}
push(p,opr);
push(p,*(p->s));
}
else
push(p,*(p->s));
p->s++;
}
if(*(p->s)==')')
{
opr=pop(p);
while((opr)!='(')
{
*(p->t)=opr;
p->t++;
opr=pop(p);
}
p->s++;
}
}
while(p->top!=-1)
{
char opr=pop(p);
*(p->t)=opr;
p->t++;
}
*(p->t)='\0';
}
//returns the pripority of an operator
int priority(char c)
{
if(c=='$')
return 3;
if(c=='*'||c=='%'||c=='/')
return 2;
else
{
if(c=='+'||c=='-')
return 1;
else
return 0;
}
}
// display the postfix form of the given expr
void show(struct infix p)
{
printf("%s",p.target);
}

Evaluation of postfix expression:-

a. Write a post fix expression in a string format and scan the expression character by
character.
b. If the character scanned is an operand, push that in to a stack.
c. If the character scanned is an operator, pop the two topmost elements from the stack.
Then perform the operation performed by the scanned operator between the two
popped elements from stack. Now push the result in to a stack.
d. Repeat the steps b and c for remaining all characters in postfix expression.
e. After completion of scanning the characters, pop the topmost value from the stack and
mark as final result.
Example:-

Source code:-

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#include<string.h>
#define MAX 50
struct postfix
{
int stack[MAX];
int top,nn;
char *s;
};
void initpostfix(struct postfix *);
void setexpr(struct postfix *,char *);
void push(struct postfix *,int);
int pop(struct postfix *);
void calculate(struct postfix *);
void show(struct postfix);
void main()
{
struct postfix q;
char expr[MAX];
clrscr();
initpostfix(&q);
printf("Enter postfix expression to evaluate:\t");
gets(expr);
setexpr(&q,expr);
calculate(&q);
show(q);
getch();
}
//initializes structure elements
void initpostfix(struct postfix *p)
{
p->top=-1;
}
//set s to point to given expression
void setexpr(struct postfix *p,char *str)
{
p->s=str;
}
//adds digit to the stack
void push(struct postfix *p,int item)
{
if(p->top==MAX-1)
printf("stack is full \n");
else
{
p->top++;
p->stack[p->top]=item;
}
}
//pops digit from the stack
int pop(struct postfix *p)
{
int data;
if(p->top==-1)
{
printf("stack is empty\n");
return NULL;
}
data=p->stack[p->top];
p->top--;
return data;
}
// evaluate the postfix expression
void calculate(struct postfix *p)
{
int n1,n2,n3;
while(*(p->s))
{
//skip whitespace. if any
if(*(p->s)==' '||*(p->s)=='\t')
{
p->s++;
continue;
}
//if digit is encountered
if(isdigit(*(p->s)))
{
p->nn=*(p->s)-'0';
push(p,p->nn);
}
else
{
//if operator is encountered
n1=pop(p);
n2=pop(p);
switch(*(p->s))
{
case'+':
n3=n2+n1;
break;
case'-':
n3=n2-n1;
break;
case'/':
n3=n2/n1;
break;
case'*':
n3=n2*n1;
break;
case'%':
n3=n2%n1;
break;
case'$':
n3=(int)pow(n2,n1);
break;
default:
printf("unknown operator\n");
exit(1);
}
push(p,n3);
}
p->s++;
}
}
//displays the result
void show(struct postfix p)
{
p.nn=pop(&p);
printf("result is %d",p.nn);

}
QUEUES
Queue:- Queue is linear data structures in which insertion of new elements takes place at one
end called rear, and deletion of existing elements takes place from another end called front.

FIFO:- The queue is also called first in first out system because of first inserted element is
deleted first.

The two changes that can be made to a queue are given special names:

 When an item is added at rear end to queue , the operation is called Enqueue
 When an item is removed from front end of the queue, the operation is called
Dequeue.

So, the operations we are going to perform on queues are

 Enqueue: allows adding a new element at rear end of queue


 Dequeue: allows to remove an existing element from front end of queue.

We can implement the queues in two ways

 Implementation of Queues using arrays


 Implementation of queues using linked lists

Implemetation of queues using arrays:-

An array is used to store the ordered list of elements. Hence it is very easy to manage
a queue if we represent it using arrays. However the problem with an array is that we are
required to declare the size of the array before using it in a program.

Though an array and queues are totally different data structures, an array can be used
to store the elements in a queue. We can declare the array with maximum size large enough
to manage queue.
Suppose if the user wants to insert on more item to the queue, do the following:

 Increment the rear position by one.


 Check whether it is with in the limit.
 If it is within the limit, insert a new element at this position.

Suppose if the user wants to delete an existing element from the queue, do the
following:

 The element at the position pointed out by front will be removed


 The front position will be incremented by one.

The element The element


in Front in rear
position position
0 1 2 3 4

To implement the queue using array, the following are required:

 One-dimensional array
 A variable to indicate the front position
 Another variable to indicate the rear position.

PROGRAM:-

#include<stdio.h>

#include<conio.h>

#define MAX 10

struct queue

int arr[MAX];

int front,rear;

};
void enqueue(struct queue *,int );

void dequeue(struct queue *);

void main()

struct queue *p;

int k;

clrscr();

p->front=p->rear=-1;

enqueue(p,23);

enqueue(p,9);

enqueue(p,11);

enqueue(p,18);

enqueue(p,25);

enqueue(p,16);

enqueue(p,17);

enqueue(p,22);

enqueue(p,19);

enqueue(p,30);

printf("queue after inserting elements:\n");

for(k=p->front;k<MAX;k++)

printf("%d\t",p->arr[k]);
enqueue(p,30);

dequeue(p);

dequeue(p);

dequeue(p);

printf("\n\nthe array after deleting elements from queue \n");

for(k=p->front;k<MAX;k++)

printf("%d\t",p->arr[k]);

getch();

//adds an element to the queue

void enqueue(struct queue *l,int item)

if(l->rear==MAX-1)

printf("\nQueue is full");

return;

}
l->rear++;

l->arr[l->rear]=item;

if(l->front==-1)

l->front=0;

// removes an element from the queue

void dequeue(struct queue *l)

int data,k;

if(l->front==-1)

printf("\n Q is empty");

return;

data=l->arr[l->front];

l->arr[l->front]=NULL;

if(l->front==l->rear)

l->front=l->rear=-1;

else

l->front++;

printf("\n\nthe item deleted from queue is: %d",data);

}
Implementation of queues using linked lists:-

It is not possible to predict the size of the queue in advance and it may vary from time
to time. Hence array implementation may not be possible. To overcome this draw back linked
list implementation can be used.

To represent a queue using linked list, the following are required:

 Singly linked list


 Front pointer
 Rear pointer

Source code:-
#include<stdio.h>
#include<conio.h>
#include<alloc.h>

struct queue // structure containing a data part and link part


{
int data;
struct queue *link;
};

void addq(struct queue **,struct queue **,int);


void display(struct queue *);
int delq(struct queue **,struct queue **);

void main()
{
struct queue *front,*rear;
front=rear=NULL; //empty linked list

addq(&front,&rear,10);
addq(&front,&rear,17);
addq(&front,&rear,18);
addq(&front,&rear,5);
addq(&front,&rear,30);
addq(&front,&rear,15);

clrscr();

printf("before deletion:\n");
display(front);

delq(&front,&rear);
delq(&front,&rear);
delq(&front,&rear);
printf("\nafter deletion:\n");
display(front);

getch();
}

// adds a new element at the end of the queue


void addq(struct queue **f,struct queue **r,int item)
{
struct queue *temp;
//create a new node
temp=malloc(sizeof(struct queue));
temp->data=item;

//if the queue is empty


if(*f==NULL)
*f=temp;
else
(*r)->link=temp;
*r=temp;
(*r)->link=NULL;
}

// removes an element from front of queue


int delq(struct queue **f,struct queue **r)
{
struct queue *temp;
int item;
//if queue is empty
if(*f==NULL)
printf("queue is empty");
else
{
if(*f==*r)
{
item=(*f)->data;
free(*f);
*f=NULL;
*r=NULL;
}
else
{
// delete the node
temp=*f;
item=temp->data;
*f=(*f)->link;
free(temp);
}
return(item);
}
return NULL;
}

// display whole of the queue

void display(struct queue *f)


{
printf("\n");

//traverse the entire linked list


while(f!=NULL)
{
printf("%d\t",f->data);
f=f->link;
}
}

Advantages:-

 No wastage of memory
 Insertion and deletion operations are easy to do
 Size of the queue is not fixed. Hence any number of elements can be place in a
queue dynamically.

Circular queue:-

The queue that we implemented using an array suffers from on limitation. In that
implementation there is a possibility that the queue is reported as full (since rear has
reached the end of the array), even though there might be empty slots at the beginning of
the queue.

This disadvantage can be overcome by using the circular array representation of the
queue.

n 2

N-1 3
Rear

. . . . 4
Front

. . . . 5

Fig : Circular Queue

(Logical)

here as we go on adding elements to the queue and reach the end of the array,
the next element is stored in the first slot of the array(provided it is free).

Suppose an array arr of n elements is used to implement a circular queue. Now


if we go on adding elements to the queue we may reach arr[n-1]. We cannot add any more
elements to the queue since we have reached the end of array.

Instead of reporting the queue as full, if some elements in the queue have
been deleted then there might be empty slots at the beginning of queue. In such case these
slots would be filled by a new elements being added to the queue. In short just because
we have reached the end of the array the queue would not be reported as full.
The queue would be reported as full only when all the slots in the array stand
occupied.

In circular queue, the empty or full conditions are verified as follows :

a) If the circular queue is empty then FRONT = REAR = -1

b) If the circular is full then FRONT = (REAR MOD LENGTH) + 1

ADT for Queues :

i. Enqueue () : adds an item to the rear of the queue.

ii. Dequeue () : removes and returns an item from the front end of the queue

Source code:-

#include<stdio.h>

#include<conio.h>

#define MAX 10

struct cirq

int arr[MAX];

int front,rear;

};

void addq(struct cirq *,int);

void delq(struct cirq *);


void main()

struct cirq *p;

int i;

clrscr();

p->front=p->rear=-1;

addq(p,23);

addq(p,9);

addq(p,11);

addq(p,10);

addq(p,25);

printf("\nqueue after inserting the 5 elements: ");

for(i=0;i<MAX;i++)

printf("%d\t",p->arr[i]);

delq(p);

delq(p);

delq(p);
printf("\nthe elements after deletion:");

for(i=0;i<MAX;i++)

printf("%d\t",p->arr[i]);

addq(p,21);

addq(p,17);

addq(p,18);

addq(p,14);

addq(p,20);

printf("\nelements in the circular queue after addition:\n");

for(i=0;i<MAX;i++)

printf("%d\t",p->arr[i]);

addq(p,32);

addq(p,35);

addq(p,38);

printf("\nelements in the circular queue after addition:\n");

for(i=0;i<MAX;i++)

printf("%d\t",p->arr[i]);

addq(p,40);

getch();

}
//adds an element to the queue

void addq(struct cirq *p, int item)

if(((p->rear==MAX-1)&&(p->front==0))||(p->rear+1==p->front))

printf("\nQueue is full\n");

return;

if(p->rear==MAX-1)

p->rear=0;

else

p->rear++;

p->arr[p->rear]=item;

if(p->front==-1)

p->front=0;

// removes an element from the queue

void delq(struct cirq *p)

int data;

if(p->front==-1)
{

printf("\n Q is empty");

return;

data=p->arr[p->front];

p->arr[p->front]=NULL;

if(p->front==p->rear)

p->front=p->rear=-1;

else

if(p->front==MAX-1)

p->front=0;

else

p->front++;

printf("\n the deleted item is: %d\n",data);

APPLICATIONS OF QUEUES

The important applications of queue data structures are in

a) Operating systems

b) Multiprogramming environments
c) Implementing various algorithms.

i. CPU Scheduling in Multiprogramming Environment :

In multiprogramming environment, a single CPU has to serve more than one


program simultaneously. Such as,

- interrupts to be serviced

- Interactive users to be serviced

- batch jobs to be serviced

ii. Round Robin Algorithm

Circular queue is used to implement this algorithm.

Consider there are n processes P1,P2,P3,……,Pn required to be served by CPU.

Different processes require different execution time. The sequence of processes

Arrival are P1,P2,P3,……,Pn .

This algorithm decides a smallest unit of time called a time quantum or time slice T.

This time slice is usually from 10 to 100ms. Hence, CPU starts servicing process P1.

P1 gets CPU time for T instant of time. Then CPU switches to P2 , and so on.

When CPU reaches the end of time quantum of Pn it returns to P1 and the same

Process will be repeated.

Suppose if some process finishes its execution before its time quantum is finished the

Process simply releases the CPU.

So the next process gets the CPU and will be serviced.

Example :

process Burst-time

P1 5

P2 3

P3 10 Here, time slice is 2.


Advantage :

Average turn around time is reduced.

You might also like