0% found this document useful (0 votes)
44 views39 pages

Understanding Stack and Queue Data Structures

Uploaded by

manjudivakaran06
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)
44 views39 pages

Understanding Stack and Queue Data Structures

Uploaded by

manjudivakaran06
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

MODULE 02 STACK AND QUEUES

Stack

• A Stack is a linear data structure that follows the LIFO (Last-In-


First-Out) principle.
• It is a data structure where insertion and deletion takes place at
one end.
• It contains one pointer, top pointing to the topmost element of
the stack.
• Two operations performed on stack are push [to insert] and pop
[to delete] elements from the stack.

A stack can be defined as a container in which insertion and deletion


can be done from the one end known as the top of the stack.
Some key points related to stack

o It is called as stack because it behaves like a real-world stack,


piles of books, etc.
o A Stack is an abstract data type with a pre-defined capacity,
which means that it can store the elements of a limited size.
o Last item added to the stack is first to be removed.
o Stack can be implemented using array and linked list.

Array Implementation of stack

Stack is an ordered collection of elements and it can be implemented


using array.

Stack implemented using array is called static stack. Here array sizes
should be declared earlier.

Working of Stack [push and pop]

Stack works on the LIFO pattern. Suppose we want to store the


elements in a stack and let's assume that stack is empty. We have
taken the stack of size 5 as shown below in which we are pushing the
elements one by one until the stack becomes full.
The stack gets filled up from the bottom to the top.

When we perform the delete operation on the stack, there is only one
way for entry and exit as the other end is closed. It follows the LIFO
pattern, which means that the value entered first will be removed last.

Standard Stack Operations

The following are some common operations implemented on the


stack:

o push(): When we insert an element in a stack then the operation


is known as a push. If the stack is full then the overflow
condition occurs.
o pop(): When we delete an element from the stack, the operation
is known as a pop. If the stack is empty means that no element
exists in the stack, this state is known as an underflow state.
o isEmpty(): It determines whether the stack is empty or not.
o isFull(): It determines whether the stack is full or not.'
o peek(): Get the value of the top,without removing it.
o count(): It returns the total number of elements available in a
stack.
o change(): It changes the element at the given position.
o display(): It prints all the elements available in the stack.

PUSH operation

The steps involved in the PUSH operation is given below:

o Before inserting an element in a stack, we check whether the


stack is full.
o If we try to insert the element in a stack, and the stack is full,
then the overflow condition occurs.
o When we initialize a stack, we set the value of top as -1 to check
that the stack is empty.
o When the new element is pushed in a stack, first, the value of
the top gets incremented, i.e., top=top+1, and the element will
be placed at the new position of the top.
o The elements will be inserted until we reach the max size of the
stack.
Stack is a data structure implemented using array,

Max is the maximum size of the array,

Top is a pointer pointing to the top of the stack,

Item is the element to be inserted to the top of stack.

Algorithm: PUSH[Operation in Stack]

Step 1: If Top==Max-1

Print “Overflow : Stack is full” and Return Null

End If

Step 2: Top=Top+1

Step 3: Stack[Top]=Item

Step 4: Return
POP operation

The steps involved in the POP operation is given below:

o Before deleting the element from the stack, we check whether


the stack is empty.
o If we try to delete the element from the empty stack, then
the underflow condition occurs.
o If the stack is not empty, we first access the element which is
pointed by the top
o Once the pop operation is performed, the top is decremented by
1, i.e., top=top-1.

Stack is a data structure implemented using array. Top is a pointer


pointing to the top of the stack. Item is the element to be inserted to
the top of stack.

Algorithm: POP Operation in Stack

Step 1: If TOP==-1

Print “Underflow: Stack is empty” and Return Null

End if

Step 2: Set Item=Stack[Top]

Step 3: Top=Top-1
Step 4: Return Item

Applications of Stack Data Structure

Although stack is a simple data structure to implement, it is very


powerful. The most common uses of a stack are:

• To reverse a word - Put all the letters in a stack and pop them
out. Because of the LIFO order of stack, you will get the letters in
reverse order.

• In compilers - Compilers use the stack to calculate the value of


expressions like 2 + 4 / 5 * (7 - 9) by converting the expression to
prefix or postfix form. Expression evaluation and expression
conversion can be done using stack.

• In browsers - The back button in a browser saves all the URLs


you have visited previously in a stack. Each time you visit a new
page, it is added on top of the stack. When you press the back button,
the current URL is removed from the stack, and the previous URL is
accessed.

• Undo Mechanism

• Traversing tree and graph


• Backtracking - Suppose we have to create a path to solve a
maze problem. If we are moving in a particular path, and we realize
that we come on the wrong way. In order to come at the beginning of
the path to create a new path, we have to use the stack data structure.

• Memory management: The stack manages the memory. The


memory is assigned in the contiguous memory blocks.

• Recursion: The recursion means that the function is calling


itself again. To maintain the previous states, the compiler creates a
system stack in which all the previous records of the function are
maintained.

Application of stack –

Expression Conversion
Infix to postfix
Infix to prefix
Postfix to infix
Prefix to infix

The way to write arithmetic expression is known as a notation. An


arithmetic expression can be written in three different but equivalent
notations, i.e., without changing the essence or output of an
expression. These notations are −

• Infix Notation
• Prefix (Polish) Notation
• Postfix (Reverse-Polish) Notation
These notations are named as how they use operator in expression.
We shall learn the same here in this chapter.

Infix Notation

We write expression in infix notation, e.g. a - b + c, where operators


are used in-between operands. It is easy for us humans to read, write,
and speak in infix notation but the same does not go well with
computing devices. An algorithm to process infix notation could be
difficult and costly in terms of time and space consumption.

Prefix Notation

In this notation, operator is prefixed to operands, i.e. operator is


written ahead of operands. For example, +ab. This is equivalent to its
infix notation a + b. Prefix notation is also known as Polish
Notation.

Postfix Notation

This notation style is known as Reversed Polish Notation. In this


notation style, the operator is postfixed to the operands i.e., the
operator is written after the operands. For example, ab+. This is
equivalent to its infix notation a + b.
The following table briefly tries to show the difference in all three
notations −

[Link]. Infix Notation Prefix Notation Postfix Notation

1 a+b +ab ab+

2 (a + b) ∗ c ∗+abc ab+c∗
3 a ∗ (b + c) ∗a+bc abc+∗

4 a/b+c/d +/ab/cd ab/cd/+

5 (a + b) ∗ (c + d) ∗+ab+cd ab+cd+∗

Parsing Expressions

As we have discussed, it is not a very efficient way to design an


algorithm or program to parse infix notations. Instead, these infix
notations are first converted into either postfix or prefix
notations and then computed.
To parse any arithmetic expression, we need to take care of operator
precedence and associativity also.

Precedence

When there are more operators in an expressions the evaluation is


done using precedence. For example −

As multiplication operation has precedence over addition, b * c will


be evaluated first. A table of operator precedence is provided later.
Algorithm for infix to postfix conversion
1. Scan the infix expression from left to right.
2. If the scanned character is an operand, output it.
3. Else,
1 If the precedence of the scanned operator is greater than the
precedence of the operator in the stack(or the stack is empty or the
stack contains a ‘(‘ ), push it.
2 Else, Pop all the operators from the stack which are greater
than or equal to in precedence than that of the scanned operator.
After doing that Push the scanned operator to the stack. (If you
encounter parenthesis while popping then stop there and push the
scanned operator in the stack.)
4. If the scanned character is an ‘(‘, push it to the stack.
5. If the scanned character is an ‘)’, pop the stack and output it until a
‘(‘ is encountered, and discard both the parenthesis.
6. Repeat steps 2-6 until infix expression is scanned.
7. Print the output
8. Pop and output from the stack until it is not empty.
A+B*(C^D-E)

(A+B/C*(D+E)-F)
Algorithm for infix to prefix conversion
As an example, consider the problem of finding the factorial of a positive
integer,

double fact(int n)

if (n = = 0)

return 1;

else

return n*fact(n-1);

}
STACK USING LINKED LIST

Advantages of Linked List

Dynamic Data Structure

Linked list is a dynamic data structure so it can grow and shrink at


runtime by allocating and de allocating memory. So there is no need
to give initial size of linked list.

Insertion and Deletion

Insertion and deletion of nodes are really easier. Unlike array here we
don’t have to shift elements after insertion or deletion of an element.
In linked list we just have to update the address present in next pointer
of a node.

Stack using linked list


Syntax of linked list

struct node
{
int data;
struct node *next
}*top;

push(value) - Inserting an element into the Stack

We can use the following steps to insert a new node into the stack

PUSH[Stack,Top,Item]

• Step 1 - Create a New node.


• Step 2 – Info[New Node]=Item
• Step 2 - Check whether stack is Empty (top == NULL)
• Step 3 – Top = Newnode
• Step 3 - If it is Empty, then set next[Top] = NULL.
• Step 4 - If it is Not Empty, then set next [NewNode]= top.
• Step 5 - Finally, set top = Newnode.
• Step 6 – Return
pop() - Deleting an Element from a Stack

We can use the following steps to delete a node from the stack.

PUSH[Stack,Top,]

• Step 1 - Check whether stack is Empty (top == NULL).


• Step 2 - If it is Empty, then display "Stack is Empty!!!
Deletion is not possible!!!" and terminate the function.
• Step 3 - If it is not empty set Top = Next[Top]
• Step 4 – Item = Info[Top]
• Step 5 - Return
Queue
A queue can be defined as an ordered list of elements which
enables insertion of elements can take place at only one end
called REAR and delete operations can take place at another end
called FRONT.

Queue is referred to be as First In First Out list. First element


entered the queue will be the first to go out.

For example, people waiting in line for a rail ticket form a queue.

Applications of Queue

Due to the fact that queue performs actions on first in first [Link]
are various applications of queues discussed as below.

1. Queues are widely used as waiting lists for a single shared


resource like printer, disk, CPU.
2. Queues are used in asynchronous transfer of data (where data is
not being transferred at the same rate between two processes)
for eg. pipes, file IO, sockets.
3. Queues are used as buffers in most of the applications like MP3
media player, CD player, etc.
4. Queues are used to maintain the play list in media players in
order to add and remove the songs from the play-list.

Basic Operations of Queue

A queue is an object (an abstract data structure - ADT) that allows


the following operations:

• Enqueue: Add an element to the end of the queue


• Dequeue: Remove an element from the front of the queue
• IsEmpty: Check if the queue is empty
• IsFull: Check if the queue is full
• Peek: Get the value of the front of the queue without removing it
Array Implementation of Queue
Queue is an ordered collection of elements and it can be
implemented using array.
A queue can be represented in a program by using a linear array of
elements and three pointer variables FRONT, REAR and MAX.

The queue is empty if FRONT = REAR = -1. The queue is full if FRONT
=1 and REAR = MAX - 1.

The size of the above queue is 5. It has 3 elements A, B and C. The FRONT,
REAR and MAX pointers will have values 0, 2 and 5 respectively.

Whenever an element is deleted from the queue the value of FRONT is


increased by 1;
FRONT:=FRONT +1
Whenever an element is inserted to the queue the value of REAR is
increased by 1;
REAR:=REAR +1
The REAR element of the queue will occupy QUEUE [N-1]; or the queue will
occupy the last part of the array. This occurs even though the queue itself
may not contain many elements. Ie,QUEUE IS FULL.

Enqueue Operation[insertion]

Queues maintain two data pointers, front and rear. Therefore, its
operations are comparatively difficult to implement than that of
stacks.

The following steps should be taken to enqueue (insert) data into a


queue −

• Step 1 − Check if the queue is full.


• Step 2 − If the queue is full, produce overflow error and exit.

• Step 3 − If the queue is not full, increment rear pointer to point


the next empty space.

• Step 4 − Add data element to the queue location, where the rear
is pointing.

• Step 5 − return success.


Dequeue Operation

Accessing data from the queue is a process of two tasks − access the
data where front is pointing and remove the data after access.

The following steps are taken to


perform dequeue operation[deletion operation] −

• Step 1 − Check if the queue is empty.

• Step 2 − If the queue is empty, produce underflow error and


exit.

• Step 3 − 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.

• Step 5 − Return success.


Algorithm: Insert Operation on Queue
INSERT[Queue,Front,Rear,Item]

Step 1: If Rear=Max-1

Print “Overflow : Queue is full” and Exit

Step2: Else IF Front = -1 and Rear = -1


SET FRONT = REAR = 0

Queue[Rear]=Item

Step 3: Else set Rear=Rear+1

Step 4: Queue[Rear]=Item

Step 5: End

Algorithm: Delete Operation on Queue

DELETE[Queue,Front,Rear,Item]

Step 1: If Front=-1 or Front >Rear

Print “Underflow: Queue is empty” and Exit

End if

Step 2: Set Item=Queue[Front]


Step 3: If Front=Rear

Set Front=Rear=-1

Else

Step 4; Front=Front+1

End If

Step 5: Return Item

Step 5: End

QUEUE USING LINKED LIST

Queue can also be represented using linked list. Lined list does not
have any restriction on elements it can hold.
struct node
{
int data;
struct node *next;
}*front, * rear;
The major problem with the queue implemented using an array is, It
will work for an only fixed number of data values. That means, the
amount of data must be specified at the beginning itself. Queue using
an array is not suitable when we don't know the size of data which we
are going to use.
The HEAD pointer of the linked list is used as the FRONT. Also, use another
pointer called REAR to store the address of the last element of the queue.

enQueue(value) - Inserting an element into the Queue


We can use the following steps to insert a new node into the queue...

• Step 1 - Create a newNode with info['newNode] =item and set


next['newNode] to NULL.
• Step 2 - Check whether queue is Empty (front==rear == NULL)
• Step 3 - If it is Empty then,
set front = newNode and rear = newNode.
• Step 4 - If it is Not Empty then,
set next[rear] = newNode and rear = newNode.
• Step 5 - Return
deQueue() - Deleting an Element from Queue
We can use the following steps to delete a node from the queue...

• Step 1 - Check whether queue is Empty (front ==


rear==NULL).
• Step 2 - If it is Empty, then display "Queue is Empty!!! Deletion
is not possible!!!" and terminate from the function
• Step 3 - If it is Not Empty then, define a Node pointer 'temp'
and set it to 'front'.
• Step 4 - Then set 'front = next[front] and delete 'temp'
(free(temp)).
DEQUE

dequeue stands for Double Ended Queue. In the queue, the insertion
takes place from one end while the deletion takes place from another
end. The end at which the insertion occurs is known as the rear end
whereas the end at which the deletion occurs is known as front end

Deque is a linear data structure in which the insertion and


deletion operations are performed from both ends. We can say that
deque is a generalized version of the queue.

There are two types of Queues, Input-restricted queue, and output-


restricted queue.

1. Input-restricted queue: The input-restricted queue means that


some restrictions are applied to the insertion. In input-restricted
queue, the insertion is applied to one end while the deletion is
applied from both the ends.

2. Output-restricted queue: The output-restricted queue means


that some restrictions are applied to the deletion operation. In an
output-restricted queue, the deletion can be applied only from
one end, whereas the insertion is possible from both ends.

Operations on Deque

The following are the operations applied on deque:

o Insert at front
o Delete from end
o insert at rear
o delete from rear

Other than insertion and deletion, we can also perform peek operation
in deque. Through peek operation, we can get the front and
the rear element of the dequeue.
We can perform two more operations on dequeue:

o isFull(): This function returns a true value if the stack is full;


otherwise, it returns a false value.
o isEmpty(): This function returns a true value if the stack is
empty; otherwise it returns a false value.

Memory Representation

The deque can be implemented using two data structures,


i.e., circular array, and doubly linked list.

Circular Queue

Why was the concept of the circular queue introduced?

There was one limitation in the array implementation of Queue. If the


rear reaches to the end position of the Queue then there might be
possibility that some vacant spaces are left in the beginning which
cannot be utilized. So, to overcome such limitations, the concept of the
circular queue was introduced.
WORKING EXPLAINED

[As we can see in the above image, the rear is at the last position of
the Queue and front is pointing somewhere rather than the
0th position. In the above array, there are only two elements and other
three positions are empty. The rear is at the last position of the Queue;
if we try to insert the element then it will show that there are no empty
spaces in the Queue. There is one solution to avoid such wastage of
memory space by shifting both the elements at the left and adjust the
front and rear end accordingly. It is not a practically good approach
because shifting all the elements will consume lots of time. The
efficient approach to avoid the wastage of the memory is to use the
circular queue data structure.]

When rear = -1 we set rear = 0 and when front = n-1 we set front =0

What is a Circular Queue?

A circular queue is similar to a linear queue as it is also based on


the FIFO (First In First Out) principle except that the last
position is connected to the first position in a circular queue that
forms a circle.

Circular Queue Operations


Every queue includes two pointers, FRONT and REAR, which indicate the
position where deletion and insertion can be performed. Initially, values of
FRONT and REAR is set to -1

The circular queue is full if any of the following condition is met,

• FRONT = 0 and REAR = Max – 1


• FRONT = REAR + 1
Enqueue Operation
Inserting a new element in the position pointed by REAR is called the
enqueue operation.

• Print overflow and exit if the queue is full.


• For adding first element make FRONT = 0.
• Increment REAR by 1.
• Insert new element in the position pointed by REAR.

Dequeue Operation
Deleting an element in the position pointed by FRONT is called the
dequeue operation. We must check if the queue is empty before
deletion.

o Print underflow and exit if the queue is empty.

o Return the value pointed by FRONT.

o Increment FRONT by 1 circularly.

o Set FRONT = REAR = -1 for the last element.

Let's understand the enqueue and dequeue operation through the


diagrammatic representation.

You might also like