CS8391 Unit 2
CS8391 Unit 2
STACK ADT
3.1 INTRODUCTION
Let we consider, five discs are placed one over the other through a shaft. If we want to
insert a new disc say ‘disc 6’, it is only possible to insert the disc on the top of “disc 5”. Because
of the presence of shaft, it is not possible to insert the disc 6 in the middle of discs in the shaft.
Similarly, if we want to remove “disc 4”, it is only possible to remove “disc 5” before “disc4”.
These similar operations are carried out in Stack ADT.
♣ Stack is an ordered collection of element in which insertion & deletion operations are
restricted to one end of list.
♣ The end from which elements are added or removed to or from the list is referred as a
“TOP” of Stack.
♣ It is also referred as “Push-Down List” or “Piles”.
♣ The first element placed in the stack will be at the bottom of stack.
♣ The last element placed in the stack will be at the top of stack.
♣ The last element added to the stack is the first element to be removed. Hence stack is
referred as Last-In-First-Out (LIFO) or First-In-Last-Out (FILO) ADT.
For example, the elements going to be added in stack are {5, 7, 9, 2, 10}
Order of PUSH = 5, 7, 9, 2, 10
Order of POP = 10, 2, 9, 7, 5
Implementation of PUSH & POP operations of Stack ADT is similar to Insert Last &
Delete Last operation in List ADT using Array data structure. Instead of using “N” to
Note: indicate the end of List in List ADT, “Top” variable is used in Stack.
1. PUSH
Algorithm
Step-1: Check whether the stack is full or not (i.e.) overflow condition of stack. If yes
terminate else do next.
Step-2: Get the element from the user and increment the top variable by 1.
Step-3: Insert an element onto the array of top variable.
Data Structures Using C
2. POP
Algorithm
Step-1: Check whether the stack is empty or not (i.e.) “Under flow condition of stack”. If
yes then terminate else do next.
Step-2: Decrement the top pointer by one.
IMPLEMENTATION IN C
#include<stdio.h>
#include<conio.h>
#define SIZE 5
int stack[SIZE],top=-1;
void main()
{
int choice;
void push();
void pop();
void peek();
int isempty();
int length();
void display();
clrscr();
while(1)
{
printf("\n1.PUSH\n2.POP\n3.Display\n4.Length\n5.Peek\n6.Quit\nEnter U'r choice?\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
push();
break;
case 2:
pop();
Data Structures Using C
break;
case 3:
display();
break;
case 4:
printf("Number of Elements in the Stack is:%d\n",length());
break;
case 5:
peek();
break;
case 6:
exit(0);
break;
default:
printf("Invalid Choice\n");
}
}
}
void display()
{
int i,temp=top;
if(isempty())
{
printf("\n Stack Empty\n");
return;
}
printf("\n Elements in the Stack \n");
for(i=temp;i>=0;i--)
printf("%d\t",stack[i]);
}
void push()
{
int no;
if(top==SIZE-1)
printf("Stack is Full\n");
else
{
printf("Enter the Number\n");
scanf("%d",&no);
top++;
stack[top]=no;
display();
}
Data Structures Using C
void pop()
{
int no;
if(isempty())
{
printf("Stack is Empty\n");
top=-1;
}
else
{
no=stack[top];
printf(" %d is popped from the stack\n",no);
--top;
display();
}
}
void peek()
{
if(isempty())
{
printf("\n Stack Empty\n");
return;
}
printf("The peek value of the Stack is %d\n",stack[top]);
}
int isempty()
{
return(top==-1);
}
int length()
{
return(top+1);
}
Sample I/O
1.PUSH
2.POP
3.Display
4.Length
5.Peek
Data Structures Using C
6.Quit
Enter U'r choice?
1
Enter the Number
10
The element 10 is pushed onto the stack
1. PUSH
Data Structures Using C
Algorithm
Step-1: Create a node by using malloc( ) library function.
Step-2: Get the data value from user and assign it to the data field of new node and also
assign NULL to link field of new node.
Step-3: Assign the value of top to the link field of new node and also assign the newnode
address to the top.
4
3
2 42
1 66
0 35
4
3 30
2 42
1 66 Implementation of PUSH & POP operations of Stack ADT is similar to Insert
0 35 First & Delete First operation in List ADT using Linked list data structure.
4 Instead of using “Head” to indicate Start of List in List ADT, “Top” Pointer is
3 used in Stack.
2 42
1 66
0 35
4
3
2
1 66
0 35
Note:
Data Structures Using C
void push( )
{
create_node();
newnode->next=top;
top=newnode;
printf("The Element %d is pushed onto the Stack\n",newnode->no);
}
2. POP
Algorithm
Step-1: Check the top is NULL or not. If NULL then give user message as “stack is
empty”, else do next.
Step-2: Assign next field of top pointer to the top pointer.
void pop( )
{
temp=top;
if(top==NULL)
printf("Empty Stack\n");
else
{
top=top->next;
printf("Element %d is popped from the Stack",temp->no);
free(temp);
}
}
Let us consider Insert last & Delete last operations of List ADT are the equivalent
operations to PUSH & POP operation of Stack ADT. It is not efficient because if the
last node of linked list is known in advance, then only it is possible to perform insert
Data Structures Using C
Note: last & delete last operations in less time. But search operation is not efficient in Linked
list. So that only we perform “Insert first” as PUSH and “Delete first” as a POP
operation in Stack ADT using linked list.
IMPLEMENTATION IN C
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct node
{
int no;
struct node*next;
}*temp,*newnode,*top=NULL;
void main()
{
void create_node();
void push();
void pop();
void display();
void peek();
int length();
int choice;
clrscr();
while(1)
{
printf("\n1.PUSH\n2.POP\n3.Peek\n4.Display\n5.Length\n6.Quit\nEnter U'r Choice?\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
push();
break;
case 2:
pop();
break;
case 3:
peek();
break;
case 4:
display();
Data Structures Using C
break;
case 5:
printf("The Length of the Stack is: %d\n",length());
break;
case 6:
exit(0);
default:
printf("Invalid Choice\n");
}
}
}
void create_node()
{
newnode=(s *)malloc(sizeof(s));
printf("Enter the Number\n");
scanf("%d",&newnode->no);
newnode->next=NULL;
}
void push()
{
create_node();
newnode->next=top;
top=newnode;
printf("The Element %d is pushed onto the Stack\n",newnode->no);
}
void pop()
{
temp=top;
if(top==NULL)
printf("Empty Stack\n");
else
{
top=top->next;
printf("Element %d is popped from the Stack",temp->no);
free(temp);
}
}
void peek()
{
if(top==NULL)
printf("Empty Stack\n");
Data Structures Using C
else
printf("The peek value of stack is: %d",top->no);
}
void display()
{
if(top==NULL)
printf("Stack is Empty\n");
else
{
temp=top;
printf("The elements present in the stack :\n");
while(temp!=NULL)
{
printf("%d\t",temp->no);
temp=temp->next;
}
}
}
int length()
{
int cnt=0;
temp=top;
while(temp!=NULL)
{
++cnt;
temp=temp->next;
}
return cnt;
}
Sample I/O
1.PUSH
2.POP
3.Peek
4.Display
5.Length
6.Quit
Enter U'r Choice? 1
Enter the Number
10
The Element 10 is pushed onto the Stack
Enter U'r Choice? 1
Enter the Number
Data Structures Using C
20
The Element 20 is pushed onto the Stack
Enter U'r Choice? 1
Enter the Number
30
The Element 30 is pushed onto the Stack
Enter U'r Choice? 3
The peek value of stack is: 30
Enter U'r Choice? 5
The Length of the Stack is: 3
Enter U'r Choice? 2
Element 30 is popped from the Stack
Enter U'r Choice? 4
The elements present in the stack :
20 10
In this game, a last inserted disc in a shaft should be removed first (i.e.) logic of Stack
ADT. Here each shaft will become a stack and push and pop operation will be carried out when
discs are moved from or to the shaft.
For example, consider ‘N’ is number of disc placed in Shaft A which decides the game level.
When N=1
Data Structures Using C
When N=2,
IMPLEMENTATION IN C
#include<stdio.h>
void hanoitowers(int,char,char,char);
void hanoitowers(int n, char peg1, char peg2, char peg3)
{
if(n==1)
{
printf("\nMove disk 1 from peg %c to peg %c",peg1,peg2);
return;
}
hanoitowers(n-1,peg1,peg3,peg2);
printf("\nMove disk %d from peg %c to peg %c",n,peg1,peg2);
hanoitowers(n-1,peg3,peg2,peg1);
}
void main( )
{
int n;
printf("Enter the number of disks : ");
scanf("%d",&n);
printf("The Tower of Hanoi involves the moves :\n\n");
hanoitowers(n,'A','C','B');
return 0;
}
Data Structures Using C
Algorithm
Step-1: Make an empty stack. Read the character one by one until the end of expression or
file.
Step-2: If the character is an opening symbol then push it onto the stack.
Step-3: If it is a closing symbol, Check the stack is empty or not. If empty then report an
error.
Step-4: Otherwise, pop the stack. If the popped symbol is not matched with the
corresponding closing symbol, then report an error.
Step-5: At end of file, if the stack is not empty then report an error.
IMPLEMENTATION IN C
#include<stdio.h>
#include<conio.h>
#include<string.h>
#define valid 1
#define invalid 0
#define stack_size 9
int isempty();
int isfull();
int push(int val);
int pop(int *ptr);
int checkBalance(char expre[stack_size],int expr_len);
int top=-1,char stack[stack_size];
void main()
{
Data Structures Using C
int status;
char expr[stack_size];
clrscr();
printf("\n Enter the expression:\n");
gets(expr);
printf("%s\t%d\n",expr,strlen(expr));
status=checkBalance(expr,strlen(expr));
printf("%d\n",status);
printf("\n Expression is %s",(status)?"valid":"Invalid");
getch();
}
int isempty()
{
return(top==-1);
}
int isfull()
{
return(top==stack_size-1);
}
for(j=0;j<nop;j++)
{
if(expre[i]==open_braces[j])
if(push(expre[i])==-1)
return invalid;
else if(expre[i]==close_braces[j])
if(pop(&item)==-1 ||open_braces[j]!=item)
return invalid;
}
}
if(!isempty())
return invalid;
return valid;
}
Sample I/O 1:
Sample I/O 2:
Sample I/O 3:
Algorithm
Step-1: Make an empty stack and output file.
Step-2: Read the input expression or file until it reaches the end.
Step-3: When an Operand is read, it will be placed onto the output.
Data Structures Using C
IMPLEMENTATION IN C
#include<stdio.h>
#include<conio.h>
char post_fix[20];
case '+':
return 2;
case '-':
return 2;
case '*':
return 4;
case '/':
return 4;
case '%':
return 4;
case '^':
return 5;
case '$':
return 5;
case '(':
return 0;
case '#':
return -1;
default:
return 8;
}
}
int main( )
{
char infix[25];
clrscr();
printf("\nEnter a valid infix expression:\n");
gets(infix);
in_to_post(infix);
getch();
return 0;
}
Algorithm
Step-1: Make an empty stack & Read the element one by one until the end of input.
Step-2: If it is an operand then PUSH onto the stack.
Step-3: If it is an operator then POP the element twice from the stack and perform the
manipulation on it also PUSH the result of manipulation on to the stack.
Step-4: When end of expression is reached, POP the element from stack and write it to
output.
IMPLEMENTATION IN C
#include<stdio.h>
#include<conio.h>
struct node
{
int data;
struct node *next;
}*top=NULL,*temp=NULL,*newnode=NULL;
int stk_pop()
{
int val=0;
if(top==NULL)
printf("Stack Empty\n");
else
{
val=top->data;
top=top->next;
}
return val;
}
void main()
{
char str[50],choice;
int i,a,b;
clrscr();
printf("Enter the Postfix expree to evaluate\n");
gets(str);
for(i=0;i<strlen(str);i++)
{
choice=str[i];
switch(choice)
{
case '+':
printf("perform the operation +\n");
b=stk_pop();
a=stk_pop();
printf("Push the value %d into stack\n",a+b);
stk_push(a+b);
break;
case '-':
printf("perform the operation -\n");
b=stk_pop();
a=stk_pop();
printf("Push the value %d into stack\n",a-b);
Data Structures Using C
stk_push(a-b);
break;
case '*':
printf("perform the operation *\n");
b=stk_pop();
a=stk_pop();
printf("Push the value %d into stack\n",a*b);
stk_push(a*b);
break;
case '/':
printf("perform the operation /\n");
b=stk_pop();
a=stk_pop();
printf("Push the value %d into stack\n",a/b);
stk_push(a/b);
break;
default:
printf("Push the value %d into stack\n",atoi(&choice));
stk_push(atoi(&choice));
break;
}
}
printf("%d is the answer for ",top->data);
printf("the given postfix expression:");
puts(str);
getch();
}
♣ When the function completes its execution then it looks at the top of Pile and restores all
the registers. It then makes the return jump.
♣ Clearly, all of this work can be done by using a stack.
♣ In many systems there is no checking for the stack overflow. There is a possibility to run
out of stack space by having too many simultaneously active functions. It is always a
fatal error.
♣ Consider the following routine, which prints out a linked list. It is perfectly legal & can
be proven correct. Unfortunately, if the list contain 20,000 activation records,
(representing the nested call of line 3) then this program is likely to run out of stack
space
void PrintList(list L)
{
Top:
if(L!=NULL)
{
printf(“%d”, L->element);
L=L->next;
}
goto Top;
}
♣ This simulates the recursive call as a local function so nothing needs to be saved. The
“goto” statement is used here to show how a compiler might automatically remove the
recursion.
♣ Removal of tail recursion is simple so that some compilers are doing it automatically.
Data Structures Using C
QUEUE ADT
4.1 INTRODUCTION
Let us consider five persons are waiting in a line, in front of a ticket counter for buying
tickets. The person who is standing in front of the line will get the first ticket. Second person will
get the next ticket, and so on. If a new person wants to buy a ticket then he should stand after the
last person in a queue. These similar operations are carried out in a queue of DS.
♣ Queue ADT has an ordered collection of element in which insertion is made at one end of
list & deletion is made at the other end.
♣ The queue has two ends. The end at which insertions are made is referred to as the
“REAR” end. The end from which deletions are made is referred to as the “FRONT”
end.
♣ Front end points the first element in queue which is going to be deleted first. Rear end
points the last element in queue and used to insert a new element onto to the queue.
♣ The first element placed in a queue will be at the start of queue. The last element placed
in a queue will be at the last of the queue.
♣ Capacity of queue or Queue size determines the storage of number of element onto the
queue.
Data Structures Using C
♣ In queue, the first inserted element will be removed first. So a queue is referred as
First-In-First-Out (FIFO) or LILO (Last-In-Last-Out) ADT.
♣ If the number of elements stored onto the queue is equal to the queue size then the queue
is called as “Fully Occupied Queue”. If there is no element in queue then it is called as
“Empty Queue”.
♣ It is a simple queue structure. In which traversal operation is carried out in only one
direction i.e. from front to rear.
♣ Linear queue is mostly implemented by using Array Data Structure.
♣ To keep track of first and last element of a queue for doing deletion and insertion
operations, two integer variables are needed which will be named as “front” and “rear”
variables respectively.
♣ Initially the front & rear variables are at the same position (i.e. initialized as ‘-1’ because
‘0’ becomes a first index of Array DS).
♣ During the enqueue operation, the rear variable is incremented by one and new element is
placed on the rear position of queue. This will be repeated until it reaches the
Queue-Size, whereas front variable doesn’t change.
Data Structures Using C
♣ Front is assigned as ‘0’ when the rear is one, because front should points the element
going to be deleted first from the queue.
♣ During the Dequeue operation, the front variable is incremented one by one until all the
elements of a queue will be deleted.
♣ When the front variables value is larger than rear then both are reinitialized as minus one
i.e. queue is said to be empty.
♣ In linear queue, the Enqueue operation is performed irrespective of the position of front
variable that is after the deletion of some elements from the queue, it won’t be fully
occupied queue but we can’t perform Enqueue of new element onto the queue. So the
Queue size is not properly utilized i.e. memory is wasted. This is the main drawback of
linear queue.
1. ENQUEUE
Algorithm
Step-1: Check the queue is full or not (Rear < (Qsize – 1))
Step-2: Increment rear value by 1 and get the element from the user and store it in
the array of rear position.
Step-3: If the rear value is 0 then assign front as 0 because the front should points the
element going to be dequeued from the queue.
For example, consider a queue with size 6. Enqueue the element {14, 2}
Data Structures Using C
IMPLEMENTATION IN C
#define SIZE 10
int Q[SIZE], front= -1, rear= -1;
void Enqueue( )
{
int no;
if(rear = = (SIZE-1) )
printf("Queue is Full\n");
else
{
printf("Enter the Number\n");
scanf("%d",&no);
++rear;
Q[rear]=no;
if(rear= =0)
front=0;
printf("The %d element is enqueued onto the queue\n",no);
}
}
2. DEQUEUE
Algorithm
Step-1: Check the queue is empty or not (front= = -1)
Step-2: Increment front value by 1.
Step-3: If the rear value is less than the front then assign -1 to rear and front
variable.
For example,
Data Structures Using C
IMPLEMENTATION IN C
void Dequeue()
{
int no,i;
if(front= = -1)
{
printf("Queue is Empty\n");
}
else
{
no=Q[front];
++front;
if(rear>front)
front=rear=-1;
printf(" %d is removed from the Queue\n",no);
}
}
Data Structures Using C
IMPLEMENTATION IN C
struct node // Skeleton of Node
{
int data;
struct node *next;
};
2. ENQUEUE
Algorithm
Data Structures Using C
Step-1: Check the Front pointer is NULL or not (Queue Empty). If it is NULL then
assign newnode address to Front as well as Rear pointer, otherwise follow the next
steps.
Step-2: Call to create_node function.
Step-3: Assign new node address to the link field of Rear node and also to the Rear
node.
IMPLEMENTATION IN C
void Enqueue( )
{
if(Front= =NULL)
Front=Rear=newnode;
else
{
create_node();
Rear->next=newnode;
Rear=newnode;
}
}
3. DEQUEUE
Algorithm
Step-1: Check the Queue is empty or not. If empty then terminate the process, otherwise
assign the link field of first node (i.e. Front pointer) to the Front pointer.
Step-2: Freed the memory space of deleted node by using free( ) library function
Data Structures Using C
IMPLEMENTATION IN C
void Dequeue( )
{
if(Front= =NULL)
printf(“Queue is empty\n”);
else
{
temp= Front;
Front = Front ->next;
free(temp);
}
}
1 2
0 3
4
Data Structures Using C
♣ It is a type of queue in which traversal can be performed in only one direction from front
to rear.
♣ It is same as linear queue except that the structure of queue becomes circularly
connected. So that, it overcomes the drawback of linear queue (i.e.) memory space of
dequeued element is also used for enqueue until the queue is full.
♣ Initially the front & rear pointer are at same position (i.e., (-1)). When you insert element,
the rear pointer is incremented by one and the new element is stored on the position [rear
% Qsize] where % is a modular operation. So that, enqueue operation is carried out until
the queue is full.
♣ Front is assigned to ‘0’ when the rear is equal to one, because front should points the
element going to be deleted first from the queue.
♣ The queue is said to be fully occupied when difference of rear and front is equal to the
queue size minus one (rear-front= =Qsize-1). When rear or front has a value -1, the queue
is said to be empty queue (front= =-1).
♣ When the front value is greater than the rear then both are reinitialized as -1 i.e. queue
becomes empty.
1. ENQUEUE
Algorithm
Step-1: Check the queue is full or not (Rear-Front = = (Qsize – 1))
Step-2: Get the element from the user and Increment the rear value by 1.
Step-3: Store the input to the array of [rear mod (Qsize-1)] position.
Step-4: If the rear value is 0 then assign front as 0 because the front should points the
element going to be dequeued from the queue.
IMPLEMENTATION IN C
Data Structures Using C
#define SIZE 10
int Q[SIZE], front= -1, rear= -1;
void Enqueue( )
{
int no;
if((rear-front) = = (SIZE-1) )
printf("Queue is Full\n");
else
{
printf("Enter the Number\n");
scanf("%d",&no);
++rear;
Q[rear % SIZE]=no;
if(rear= =0)
front=0;
printf("The %d element is enqueued onto the queue\n",no);
}
}
2. DEQUEUE
Algorithm
Step-1: Check the queue is empty or not (front= = -1)
Step-2: Increment front value by 1.
Step-3: If the rear value is less than the front then assign -1 to rear and front
variable.
IMPLEMENTATION IN C
void Dequeue()
{
int no,i;
if(front= = -1)
{
printf("Queue is Empty\n");
}
else
{
no=Q[front % SIZE];
++front;
if(rear>front)
front=rear=-1;
printf(" %d is removed from the Queue\n",no);
}
Data Structures Using C
For example, consider a circular queue with size 4. Enqueue the elements {14, 2, 5, 6}.
After that Dequeue 2 elements from queue and Enqueue the element {9}.
0 1
3 2
14
14 2
14 2
Data Structures Using C
14 2
6 5
6 5
6 5
Data Structures Using C
6 5
1. ENQUEUE
IMPLEMENTATION IN C
Data Structures Using C
void Enqueue( )
{
create_node( );
if(Front= =NULL)
Front=Rear=newnode;
else
{
Rear ->next=newnode;
Rear =newnode;
newnode->next=Front;
}
newnode->next=Front;
}
2. DEQUEUE
IMPLEMENTATION IN C
void Dequeue( )
{
if(Front= =NULL)
printf(“Queue is empty\n”);
else
{
temp=Front;
if(Front->next= = Front)
{
Front=NULL;
free(temp);
}
Data Structures Using C
else
{
Front = Front->next;
free(temp);
Rear->next= Front;
}
}
}
1. Input Restricted Deque - Allow insertion at only one end and deletion in both end of
queue.
2. Output Restricted Deque - Allow deletion at only one end and insertion in both end of
queue.
Only 1st, 3rd & 4th operations are performed by the input-restricted deque and 1st, 2nd, & 4th
operations are performed by the output-restricted deque.
♣ Using Ordered Array - Insert an element into an ordered list takes O(n) time
(i.e. we have to traverse the list to find where the element is actually inserted
based on its priority). Deletion of the maximum element takes only O(1) time
because of ordered list. Since we frequently insert the data, this implementation
is not preferred.
takes only O(log n) time to complete the process. Heap is type of TREE ADT. This will be
elaborately discussed in the chapter of Balanced Trees ADT.
Enqueue Linear Queue After increment the rear A new node is inserted at
value by one, the new last of linked list using rear
element is placed at the rearth pointer
index in array
Circular Queue After increment the rear Same as Linear Queue but
value by one, the new here the last node is
element is placed at the (rear circularly connected with
% Qsize)th index in array the first node.
♣ In large universities, resources are almost limited. A student must sign a waiting list if all
terminals are occupied. According to the waiting list order the service or terminals are
allocated to a student.
♣ Queue is used for BFS implementation to traverse a graph.
♣ Round-robin processor scheduling algorithm is implemented by using queue data
structure.