0% found this document useful (0 votes)
12 views

UNIT II new

Uploaded by

SHREE LEKHA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

UNIT II new

Uploaded by

SHREE LEKHA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

UNIT II - LINEAR DATA STRUCTURES – STACKS, QUEUES

Stack ADT – Stack Model - Implementations: Array and Linked list - Applications - Balancing symbols -
Evaluating arithmetic expressions - Conversion of Infix to postfix expression- Queue ADT – Queue Model -
Implementations: Array and Linked list - applications of queues - Priority Queues - Binary Heap –
Applications of Priority Queues.
STACK ADT
A stack is a list with the restriction that inserts and deletes can be performed in only one position, namely
the end of the list called the top. Stacks are known as LIFO (Last In First Out) lists.
OPERATIONS ON STACK
There are three basic operations on a stack:
PUSH – This operation is used to insert an element to the stack.
POP – This operation is used to delete the most recently inserted element.
PEEK- This operation is used to return the topmost element of the stack.
The push and Pop operation can be represented as picture as follows,
IMPLEMENTATION OF STACK
Stack can be implemented by using the two ways.
1. Array implementation of Stack
2. LinkedList implementation of Stack
Array Implementation of Stack
A Stack is defined as a pointer to a structure. The structure contains 2 fields namely top_of_stack and
stack_size. In array implementation, the stack is formed by using the array. All the operations regarding the
stack are performed using arrays.
CONDITIONS ON STACK:
1. isFull()
if(top==MAX-1)
cout<<“Stack OVERFLOW or FULL”;

This condition is checked before performing the Push operation.


2. isEmpty()

if(top==-1)
cout<<“Stack is empty”;

PUSH and POP DEMONSTRATION


Pop 2
Push 1 Push 2

G.Vasukidevi 1
PUSH
Adding an element into the top of the stack is referred to as push operation. Push operation involves following
steps.
ALGORITHM FOR PUSH OPERATION
1. Check for the Top pointer value.
2. Check the isFull() condition.
3. If condition is true discard the operation.
4. If condition is false, Increment the Top pointer by 1 and Push the element in that Top pointer location. This
is referred to as adding new element at the top of the stack.

Code:
void push(int st[],int val)
{
if(top==Max-1)
{
cout<<“Stack is FULL”;
return -1;
}
else
{
top++;
st[top]=val;
}
}

POP Operation- Deleting an Element from the stack


Deleting an element into the top of the stack is referred to as pop operation. Pop operation involves
following two steps.

ALGORITHM FOR POP OPERATION


1. Check for the Top pointer value
2. Check the isEmpty() condition
3. If condition is true discard the operation
4. If condition is false, Decrement the Top pointer by 1 and Pop the element from the Top pointer location.

G.Vasukidevi 2
Code:
void pop(int st[])
{
if(top==-1)
{
cout<<“Stack Underflow or empty”;
return -1;
}
else
{
int x=st[top];
cout<<“\n The Deleted Element is ”<<x;
top--;
}
}
Peek operation-Returning the Topmost element in Stack
Peek() is one of a stack operation that returns the value of the top most element of the stack without deleting
that element from the stack.
Code:
int peek(int st[])
{
if(top==-1)
{
cout<<“\n Stack is Empty”;
return -1;
}
else
{
return st[top];
}
}
LINKED LIST REPRESENTATION OF STACK
A Linked List is a Data Structure which consists of two parts:
struct node
{
int data;
struct node *next; // The pointer which gives the location of the next node in the list.
};
struct node *top=NULL;
Stack can also be represented by using a linked list. We know that in the case of arrays we face a
limitation , i.e , array is a data structure of limited size. Hence before using an array to represent a stack we
will have to consider an enough amount of space to suffice the memory required by the stack.
G.Vasukidevi 3
Operations on Linked list implementation of Stack
1. Push
2. Pop
3. Peek

Push operation- Adding a node to the stack


Adding a node to the stack is referred to as push operation. Pushing an element to a stack in linked list
implementation is different from that of an array implementation. To push an element onto the stack, the
following steps are involved.
1. Create a node first and allocate memory to it.
2. If the list is empty, then the item is to be pushed as the start node of the list. This includes assigning
value to the data part of the node and assign NULL to the address part of the node.
3. If there are some nodes in the list already, then we must add the new element in the beginning of the list
(to not violate the property of the stack). For this purpose, assign the address of the starting element to
the address field of the new node and make the new node, the starting node of the list.
Time Complexity: o (1)
Before Push

After Push

G.Vasukidevi 4
CODE:
void push ()
{
int val;
struct node *new =(struct node*)malloc(sizeof(struct node));
cin>>val;
if(top==NULL)
{
new->val = val;
new -> next = NULL;
top=new;
}
else
{
new->val = val;
new->next = top;
top=new;
}
}
POP operation- Deleting a node from the stack
Deleting a node from the top of stack is referred to as pop operation. Deleting a node from the linked list
implementation of stack is different from that in the array implementation. In order to pop an element from
the stack, we need to follow the following steps:
1. Check for the underflow condition: The underflow condition occurs when we try to pop from an already
empty stack. The stack will be empty if the head pointer of the list points to null.
2. Adjust the head pointer accordingly: In stack, the elements are popped only from one end, therefore,
the value stored in the head pointer must be deleted and the node must be freed. The next node of the head
node now becomes the head node.
Time Complexity: o(n)
Before Pop

After Pop

G.Vasukidevi 5
void pop()
{
struct node *t;
if (top == NULL)
{
cout<<"Stack is empty or Underflow"<<endl;
return -1;
}
else
{
t=top;
top = top->next;
free(t);
}
}
Peek operation
Display the last element in the stack.
CODE
void peek()
{
if (top == NULL)
{
cout<<" Stack is empty or Underflow"<<endl;
}
else
{
cout<<top->data;
}
}

Display the nodes (Traversing)


Displaying all the nodes of a stack needs traversing all the nodes of the linked list organized in the form of
stack. For this purpose, we need to follow the following steps.
1. Copy the head pointer into a temporary pointer.
2. Move the temporary pointer through all the nodes of the list and print the value field attached to every node.
Time Complexity: o(n)
CODE:
void display()
{
int i;
struct node *ptr;
ptr=top;
G.Vasukidevi 6
if(ptr == NULL)
{
cout<<"Stack is empty"<<endl;
return -1;
}
else
{
while(ptr->next!=NULL)
{
cout<<ptr->data<<endl;
ptr = ptr->next;
}
cout<<ptr->data;
}
}

Applications of Stacks
The Application of Stacks are:
1. Reverse a list
2. Parenthesis Checker
3. Conversion of Infix Expression to Postfix Expression
4. Evaluation of Postfix Expression
5. Conversion of infix to prefix expression
6. Evaluation of Prefix Expression
7. Recursion
8. Tower of Hanoi

1. Implementation of Parenthesis Checker


Stacks can be used to check the validity of parentheses in any algebraic expression, and it is used to check
whether the parentheses in any algebraic expression are balanced.
Valid:
If the parenthesis are equally balanced then it is valid.
If for every open bracket there is a corresponding closing bracket.
Eg:
{( a + b ) * [( c + d )/e] }
Invalid:
If the parenthesis are unequal and not of same type then it is invalid expression
Eg:
{( a + b ) * ( c + d )/e] } is invalid as the corresponding opening bracket of ] is missing.
Algorithm:
1. Make an empty stack.
2. Read characters until end of an expression
a. If the character is an open parenthesis, push it onto the stack.

G.Vasukidevi 7
b. If it is a close parenthesis,
then if the stack is empty
report an error,
otherwise pop one parenthesis from stack.
d. if the parenthesis which is popped from stack is not matching with corresponding opening parenthesis,
then report an error.
3. At the end of the file, if the stack is not empty report an error.
Example 1:
[a-{b+(c+d)+e}-f]

G.Vasukidevi 8
Example 2:
{(A+B)-[(C-D)*E]
2. Conversion of Infix expression to postfix expression:
Expression:
It is the combination of operand and operator.
Eg:
a+b*c
Types of Expression:
1. Infix Expression
Operator should be in between the operands.
Syntax: operand 1 operator operand2
Eg:
a+b
2. Postfix Expression
Operator should be after the operands.
Syntax: operand 1 operand2 operator
Eg:
ab+
3. Prefix Expression
Operator should be placed before the operands.
Syntax: operator operand 1 operand2
Eg:
+ab
Steps to be followed for converting infix expression to postfix:
1. Make the stack empty.
2. Scan the infix expression, character by character from left to right until the end of an expression.
3. If the scanned character is an open parenthesis, then push that parenthesis into the stack.
4. If the scanned character is an operand (whether a digit or a character), then add it to the output (postfix
expression).
5. If the scanned character is a close parenthesis, then
a. Repeatedly pop the elements (operators) from the stack till corresponding closing parenthesis and
add it to the output (postfix expression).
b. Discard the opening parenthesis which is popped from the stack and do not add it to the postfix
expression.
6. If the scanned character is an operator, then
a. If the scanned operator is lesser precedence than the operator in the top of the stack, then
pop the operator from stack and add that operator (popped from the stack) to the
postfix expression. Push the scanned operator to the stack.
b. If the scanned operator is greater precedence than the operator in the top of the stack, then push
the scanned operator into the stack.
6. Repeatedly pop from the stack and add it to the postfix expression until the stack is empty.

G.Vasukidevi 9
Example 1:
Convert the following infix expression to postfix expression [(a+b) *(c+d/f)] - g
Step 1: When [is encountered, push it onto the stack

Stack Output
Step 2: When ( is encountered , push it onto the stack

Stack Output
Step 3: When a is encountered, it is an operand so display it on the output (postfix expression)

Stack Output
Step 4: When + is encountered, it is an operator so push it on to the stack.

Stack Output
Step 5: When b is encountered, it is an operand so display it on the output (postfix expression)

Stack Output
Step 6: When ) is encountered , pop the stack till corresponding ( and display all the symbols on the output .

Stack Output
Step 7: When * is encountered, it is an operator so push it on to the stack.

G.Vasukidevi 10
Stack Output
Step 8: When ( is encountered, push it on to the stack.

Stack Output
Step 9: When c is encountered, it is an operand so display it on the output (postfix expression

Stack Output
Step 10: When + is encountered, it is an operator so push it on to the stack.

Stack Output
Step 11: When d is encountered, it is an operand so display it on the output (postfix expression)

Stack Output
Step 12: When / is encountered, it is an operator so push it on to the stack.

Stack Output
Step 13: When f is encountered, it is an operand so display it on the output (postfix expression)

G.Vasukidevi 11
Stack Output
Step 14: When ) is encountered, pop the stack till corresponding ( is seen on the stack and display all the
popped symbols on the output (postfix expression)

Stack Output
Step 15: When ] is encountered, pop the stack till corresponding [ is seen on the stack and display all the
popped symbols on the output (postfix expression)

Stack Output
Step 16: When - is encountered, it is an operator so push it on to the stack.

Stack Output
Step 17: When g is encountered, it is an operand so display it on the output (postfix expression)

Stack Output
Step 18: We have reached the end of the infix expression, hence pop the stack till it becomes empty and
display the popped symbols on the output.

Stack Output

The resultant postfix expression is ab+cdf/+*g

G.Vasukidevi 12
Example 2:
Convert the following infix expression into postfix expression using the algorithm given below
(A – (B / C + (D % E * F) / G)* H)
Steps to perform infix to Postfix:

Example 3:
Consider the following Infix Expression to be converted into Postfix Expression...
D=A+B*C
• Step 1 - The Operators in the given Infix Expression : = , + , *
• Step 2 - The Order of Operators according to their preference : * , + , =
• Step 3 - Now, convert the first operator * ----- D = A + B C *
• Step 4 - Convert the next operator + ----- D = A BC* +
• Step 5 - Convert the next operator = ----- D ABC*+ =
Finally, given Infix Expression is converted into Postfix Expression as follows... D A B C * + =

Example 4:
Convert the following Infix Expression to postfix expression... ( A + B ) * ( C - D )

Example 5:
Convert the following Infix Expression to postfix expression A – (B / C + (D % E * F) / G)* H

G.Vasukidevi 13
Evaluation of Postfix Expression using Stack:
A postfix expression can be evaluated using the Stack data structure. To evaluate a postfix expression
using Stack data structure we can use the following steps...

Algorithm:
1. Read all the symbols one by one from left to right in the given Postfix Expression
2. If the reading symbol is operand, then push it on to the Stack.
3. If the reading symbol is operator (+, - , *, / etc.),
a. Then perform TWO pop operations and store the two popped operands in two
variables (operand1 and operand2).
b. Then perform operation using the read operator, operand1 & operand2 and push result back
on to the Stack.
4. Finally perform a pop operation and display the popped value as a final result.

Example:
Consider the following Example:
Infix Expression: (5+3) * (8-2)
Postfix Expression: 5 3 + 8 2 - *

G.Vasukidevi 14
3. Function Call
A recursive function is defined as a function that calls itself to solve a smaller version of its task until
a final call is made which does not require a call to itself. Since a recursive function repeatedly calls itself,
it makes use of the system stack to temporarily store the return address and local variables of the calling
function. When there is a function call, all the important information that needs to be saved, such as register
values and the return address is saved (called as either an activation record or stack frame.
Example: The program to find the factorial of a number

QUEUE ADT
A queue is an ordered collection of items where insertion is done at a end called the rear and deletion
is done at the other end called front.

Deletion Insertion

FRONT REAR
Fig 2.5:Queue ADT
Like stacks, queues are also lists, where insertion is done at one end and deletion is performed at the other end.
The technique or discipline followed by queue is FIFO(First In First Out).The first element inserted in the queue
will be the first element to be deleted.

G.Vasukidevi 15
The primitive operations of queue are
enqueue: inserts an element at the end of the list called rear end.
dequeue: deletes the element at the start of the list called the front end.
DEQUEUE(Q) ENQUEUE(X,Q)
QUEUE(Q)

Abstract model of a queue


IMPLEMENTATION OF QUEUE
Queue can be implemented by using the two ways.
1. Array implementation of Queue
2. LinkedList implementation of Stack

Array implementation of Queue


0 1 2 3 4

10 20 30
n=5

FRONT REAR

Operations
1. Enqueue (Insertion) – Inserting an element into the queue (at rear)
2. Dequeue (Deletion) – Deleting an element from the queue (at front)

CONDITIONS ON QUEUE:
isFull()
if(rear==MAX-1)
cout<<“Queue is OVERFLOW or FULL”;

This condition is checked before performing the Push operation.


isEmpty()

if(front==-1)
cout<<“Queue is empty”;
Enqueue(insertion)
1) Elements are inserted at the rear portion of queue.
2) If the queue is full no more elements can be inserted resulting in overflow condition.
3) If the queue is not full then the rear pointer is incremented and the item is inserted.

G.Vasukidevi 16
Enqueue
Algorithm
Step 1: Check if the queue is full
Step 2: If the queue is full(rear==MAX-1), produce overflow error or queue full error and exit
Step 3: Else If the queue is empty (front==-1 && rear==1) make front=rear=0
Step 4: Else increment rear (rear=rear+1)
Step 5: Add data element to the queue location, where the rear is pointing.
Routine
void enqueue(int val)
{
if(rear>=MAX-1)
cout<<“Queue overflow!”<<endl;
else if(front==1 && rear==-1)
{
front=rear=0; -1
q[rear]=val;
}
else
{
rear++;
q[rear]=val;
}
}

Dequeue(deletion)
1) Elements are deleted from the front
2) If the queue is empty it results in underflow condition
3) If the queue is not empty, delete the element from front.
0 1 2 3 4

10 20 30
n=5

G.Vasukidevi 17
FRONT REAR
0 1 2 3 4

20 30
n=5

Dequeue REAR
FRONT
Algorithm
Step 1: Check if the queue is empty
Step 2: If the queue is empty, (front==1 && rear==-1), then produce underflow error and exit.
Step 3: If the queue has only one element (front==rear), then access the data and make front=rear=-1
Step 4: If the queue is not empty, access the data where front is pointing.
Step 4: Increment front pointer to point to the next available data element
Enqueue Dequeue

Routine to perform dequeue operation


void dequeue()
{
if(rear==-1 || front==-1)
cout<<“Queue underflow”<<endl;
else if (front==rear)
{
G.Vasukidevi 18
cout<<“The deleted element is ”<<q[front];
front=rear=-1;
}
else
{
cout<<“The deleted element is ”<<q[front];
front++;
}
}
Routine to display the elements of the queue
1. Check for queue empty condition
2. If the queue is not empty print the elements from front to rear.

void display()
{
if(front==-1 && rear==-)
cout<<“Queue empty or underflow”<<endl;
else
{
for(i=front; i<= rear; i++)
cout<<q[i]<<endl;
}
}
LINKED LIST IMPLEMENTATION OF QUEUE ADT

A queue is an ordered collection of items where insertion is done at a end called the rear and deletion is done at
the other end called front. The technique or discipline followed by queue is FIFO (First In First Out) The first
element inserted in the queue will be the first element to be deleted.

DEQUEUE(Q) ENQUEUE(X,Q)
QUEUE(Q)

LINKED LIST IMPLEMENTATION OF QUEUE


Declaring a queue node Declares a node with 2 fields
1) Data
G.Vasukidevi 19
2) Pointer to next node
struct node
{
int data; // contains the data element to be stored
node *next; // contains the address of the next node
};

isEmpty()
if(front==NULL)
cout<<”queue is empty”;

Operations
1. Enqueue (Insertion) – Inserting an element at the end of the list called rear end.
2. Dequeue (Deletion) – Deleting an element at the start of the list called the front end.
ENQUEUE (INSERTION)
ALGORITHM:
1. Inserts an element to the rear end of the queue
2. If Q is empty, the new node will be inserted at rear.
3. Otherwise a rear pointer will be assigned to the last node in Q and the new node will be inserted to
rear. Routine to enqueue an element in a Queue
Before after insert new node

newnode
Enqueue the element 30
Program:
void enqueue( int val)
{
struct node newnode;
newnode=(struct node *) malloc(sizeof(struct node))’;
newnode-data=val;
newnode->next=NULL;
if(front==NULL && rear ==NULL)
front=rear=newnode;
else
{
rear->next=newnode;
rear=newnode;
}
}

G.Vasukidevi 20
DEQUEUE (DELETION)
ALGORITHM:
1. deletes an element from the front end of the queue
2. If Q->next ==NULL then display Queue empty.
3. Otherwise assign the next node after the header node as front and delete that node.

10 20
Q

After DELETION of 10: FRONT REAR

20
Q

FRONT REAR
Routine to dequeue an element from Queue
void deque(Queue Q)
{
struct node *t;
if (front==NULL && rear==NULL)
cout<<“Queue is empty”<<endl;
else
{
t=front;
front=front->next;
if(front==NULL)
rear=NULL;
free(t);
}
}

G.Vasukidevi 21
Display all node
void display()
{
if(front==NULL && rear==NULL)
cout<<Queue is underflow or empty;
else
{
for(t=front;t!=NULL;t=t->next)
cout<<t->data;
}
}

Peek
int peek()
{
if(front!=NULL)
return front->data;
else
return -1;
}

PRIORITY QUEUE
Priority queue are special kind of queue, where each element has a priority associated with it.

Two types of priority


1. Ascending priority queue - Rank
2. Descending priority queue - Mark
It is a data structure which determines the priority of jobs.
The Minimum the value of priority, higher is the priority of the job.

1. Elements with higher priority is served first.


2. If two elements have same priority, then they served according to the order in the queue (FIFO).
3. Generally, the value of the element itself is considered as a higher priority.
Implementation of Priority Queue
1. Linked list.
2. Binary search tree
3. Binary Heap

G.Vasukidevi 22
Array based implementation of Priority Queue

Operations
1. Enqueue
2. Deletemin
Enqueue
Empty Queue
-1 0 1 2 3 4

n=5

FRONT REAR

After inserted one element 5


0 1 2 3 4

5
n=5

After inserted one element 2


FRONT
0 REAR 1 2 3 4

2 5
n=5

FRONT REAR

After inserted one element 4


0 1 2 3 4

2 4 5
n=5

FRONT REAR

void enqueue(int q[], int val)


{
if(rear==MAX-1)
cout<<”Queue is full”;
G.Vasukidevi 23
else
{
pos=rear;
rear=rear+1;
while(pos>=0 &&q[pos]>=val)
{
q[pos+1]=q[pos];
pos=pos-1;
}
q[pos+1]=val;
if(front==-1)
front=front+1;
}
}

Deletemin
void deletemin()
{
if(rear==-1 || front==-1)
cout<<“Queue underflow”<<endl;
else if (front==rear)
{
cout<<“The deleted element is ”<<q[front];
front=rear=-1;
}
else
{
cout<<“The deleted element is ”<<q[front];
front++;
}
}

Linked list Implementation of Priority Queue


1. Insertion performed at the front, running time O(1) and deletion is performed by traversing the list
which requires O(N) time, to delete the minimum.
(Or)
2. Keep the list sorted always, this makes insertions expensive and deletemin cheap O(1).
Operations on Priority Queue
1. Insert
Enqueue an element into the priority queue
2. Deletemin
Dequeue highest priority (the minimum element) in the priority queue
3. Peek
G.Vasukidevi 24
Get the element at front of the queue.
1. Insert
Routine
void insert (int num)
{
new=(struct node *) malloc(sizeof(struct node));
new->data=num;
new->next=NULL;
if(front==NULL || front->data>num)
{
new->next=front; //new->next=NULL;
front=new;
}
else
{
tp=front;
t=tp->next;
while(t->next!=NULL)
{
if(t->data<num)
{
tp=t;
}
t=t->next;
}
new->next=tp->next;
tp->next=new;
}
}

2. Deletemin
void delmin()
{
if(front==NULL)
cout<<”Queue is empty”;
else
{
t=front;
front=front->next;
free(t);
}
}

G.Vasukidevi 25
Applications of Priority Queue:
• Prim's algorithm
• Dijkstra's shortest path algorithm
• A* Search algorithm
• Priority queues are used to sort heaps
• Operating system for load balancing and interrupt handling.
• Priority queues are used in Huffman codes for data compression.
• In traffic lights, depending upon the traffic, the colors will be given priority.
Binary Heap
• Binary heap is a complete Binary tree in which the value present at any node is greater than all its children.
• A Binary Heap is a complete Binary Tree that is used to store data efficiently to get the max or min
element based on its structure.
• A Binary Heap is either Min Heap or Max Heap. In a Min Binary Heap, the value at the root must be
minimum among all keys present in Binary Heap.
• Binary heap is used for implementing priority queues.

G.Vasukidevi 26

You might also like