0% found this document useful (0 votes)
3 views65 pages

Stack_Queue

The document provides an overview of data structures, focusing on stacks and queues, which are essential for organizing and manipulating data efficiently. It explains the characteristics of stacks (LIFO) and queues (FIFO), their basic operations like push, pop, enqueue, and dequeue, as well as their implementations using arrays. Additionally, it discusses the concept of circular queues and the evaluation of arithmetic expressions using stacks, highlighting the importance of different notations such as infix, prefix, and postfix.

Uploaded by

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

Stack_Queue

The document provides an overview of data structures, focusing on stacks and queues, which are essential for organizing and manipulating data efficiently. It explains the characteristics of stacks (LIFO) and queues (FIFO), their basic operations like push, pop, enqueue, and dequeue, as well as their implementations using arrays. Additionally, it discusses the concept of circular queues and the evaluation of arithmetic expressions using stacks, highlighting the importance of different notations such as infix, prefix, and postfix.

Uploaded by

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

DATA STRUCTURES

Introduction to Data Structures

• Data Structure is a way of collecting and organizing


data in such a way that we can perform operations on
these data in an effective way.

• In other words, Data Structures are structures


programmed to store ordered data, so that various
operations can be performed on it easily.
types of Data Structures
STACKS
STACK
• A stack is an Abstract Data Type (ADT), commonly
used in most programming languages.
• It is named stack as it behaves like a real-world stack,
for example – a deck of cards or a pile of plates, etc.
STACK
• A real-world stack allows operations at one end only. For
example, we can place or remove a card or plate from the
top of the stack only.
• Likewise, Stack allows all data operations at one end
only. At any given time, we can only access the top
element of a stack.

• This feature makes it LIFO data structure. LIFO stands


for Last-in-first-out.
• Here, the element which is placed (inserted or added) last,
is accessed first.
• In stack terminology, insertion operation is called PUSH
operation and deletion operation is called POP operation.
Stack Representation
The following diagram depicts a stack and its operations −
Stack Representation
• A stack can be implemented by means of Array,
Structure, Pointer, and Linked List.

• Stack can either be a fixed size one or it may have a


sense of dynamic resizing.

• Here, we are going to implement stack using arrays,


which makes it a fixed size stack implementation.
Basic Operations
Stack operations may involve initializing the stack,
using it and then de-initializing it. Apart from these
basic stuffs, a stack is used for the following two
primary operations −

• push() − Pushing (storing) an element on the stack.

• pop() − Removing (accessing) an element from the


stack.
Basic Operations
To use a stack efficiently, we need to check the status of
stack as well. For the same purpose, the following
functionality is added to stacks −

• peek() − get the top data element of the stack,


without removing it.

• isFull() − check if stack is full.

• isEmpty() − check if stack is empty.


Basic Operations
• At all times, we maintain a pointer to the last
PUSHed data on the stack.

• As this pointer always represents the top of the


stack, hence named top.

• The top pointer provides top value of the stack


without actually removing it.
peek()
Algorithm Example

• begin procedure peek • int peek()


• return stack[top] • {
• end procedure • return stack[top];
• }
isfull()
Algorithm Example

• begin procedure isfull • bool isfull()


• if top equals to MAX -1 • {
• return true • if(top == MAX-1)
• else • return true;
• return false • else
• endif • return false;
• end procedure • }
isempty()
• Implementation of isempty() function in C
programming language is slightly different.

• We initialize top at -1, as the index in array


starts from 0.

• So we check if the top is below zero or -1 to


determine if the stack is empty.
isempty()

Algorithm Example

• begin procedure isempty • bool isempty()


• if top less than 0 • {
• return true • if(top == -1)
• else • return true;
• return false • else
• endif • return false;
• end procedure • }
Push Operation
The process of putting a new data element onto stack is known as a
Push Operation. Push operation involves a series of steps −

• Step 1 − Check if the stack is full.

• Step 2 − If the stack is full, produce an error and exit.

• Step 3 − If the stack is not full, increment top to point next empty
space.

• Step 4 − Add data element to the stack location, where top is


pointing.

• Step 5 − Return success.


Push Operation
Algorithm for PUSH Operation
• begin procedure push: stack, data

• if stack is full

• return null
• endif

• top ← top + 1

• stack[top] ← data

• end procedure
Example
• void push(int data)
• {
• if(!isFull())
• {
• top = top + 1;
• stack[top] = data;
• }
• else
• {
• printf("Could not insert data, Stack is full.\n");
• }
• }
Pop Operation
• Accessing the content while removing it from the
stack, is known as a Pop Operation.

• In an array implementation of pop() operation, the


data element is not actually removed, instead top is
decremented to a lower position in the stack to point
to the next value.

• But in linked-list implementation, pop() actually


removes data element and deallocates memory space.
Pop Operation
A Pop operation may involve the following steps −

• Step 1 − Check if the stack is empty.

• Step 2 − If the stack is empty, produce an error and exit.

• Step 3 − If the stack is not empty, access the data element at


which top is pointing.

• Step 4 − Decrease the value of top by 1.

• Step 5 − Return success.


Pop Operation
Algorithm for Pop Operation

• begin procedure pop: stack

• if stack is empty

• return null
• endif

• data ← stack[top]

• top ← top - 1

• return data

• end procedure
Example
• int pop(int data)
• {
• if(!isempty())
• {
• data = stack[top];
• top = top - 1;
• return data;
• }
• else
• {
• printf("Could not retrieve data, Stack is empty.\n");
• }
• }
QUEUES
Queue
• Queue is an abstract data structure, somewhat similar
to Stacks.

• Unlike stacks, a queue is open at both its ends.

• One end is always used to insert data (enqueue) and


the other is used to remove data (dequeue).

• Queue follows First-In-First-Out (FIFO)


methodology, i.e., the data item stored first will be
accessed first.
Queue
• A real-world example of queue can be a single-lane
one-way road, where the vehicle that enters first, exits
first.
• More real-world examples can be seen as queues at
the ticket windows and bus-stops.
Queue Representation
• As we now understand that in queue, we access both ends for
different reasons. The following diagram given below tries to
explain queue representation as data structure −

• As in stacks, a queue can also be implemented using Arrays,


Linked-lists, Pointers and Structures. For the sake of
simplicity, we shall implement queues using one-dimensional
array.
Basic Operations
Queue operations may involve initializing or defining
the queue, utilizing it, and then completely erasing it
from the memory.
Here we shall try to understand the basic operations
associated with queues −

• enqueue() − add (store) an item to the queue.

• dequeue() − remove (access) an item from the queue.


Basic Operations
Few more functions are required to make the above-
mentioned queue operation efficient. These are −

• peek() − Gets the element at the front of the queue


without removing it.

• isfull() − Checks if the queue is full.

• isempty() − Checks if the queue is empty.


Basic Operations
In queue, we always dequeue (or access) data pointed
by front pointer and while enqueing (or storing) data in
the queue we take help of rear pointer.
At first rear and front is -1.when enqueue rear+
+,dequeue front ++.

Rear ---- c b a Front

Insertion Deletion
peek(): This function helps to see the data at
the front of the queue.

Algorithm Example

• begin procedure peek • int peek()


• return queue[front] • {
• end procedure • return queue[front];
• }
isfull()
• As we are using single dimension array to implement
queue, we just check for the rear pointer to reach at
MAXSIZE to determine that the queue is full.

• In case we maintain the queue in a circular linked-list,


the algorithm will differ.
isfull()
Algorithm Example

• begin procedure isfull • bool isfull()


• if rear equals to MAXSIZE-1 • {
• return true • if(rear = = MAXSIZE - 1)
• else • return true;
• return false • else
• endif • return false;
• end procedure • }
isempty()
Algorithm Example

• begin procedure isempty • bool isempty()


• if front is less than MIN OR • {
front is greater than rear • if(front < 0 || front > rear)
• return true • return true;
• else • else
• return false • return false;
• End if • }
• end procedure
Enqueue Operation
• 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.
Enqueue Operation
Algorithm for enqueue operation
• procedure enqueue(data)

• if queue is full

• return overflow

• End if

• rear ← rear + 1

• queue[rear] ← data

• return true

• end procedure
Example
• int enqueue(int data)

• if(isfull())

• return 0;

• rear = rear + 1;

• queue[rear] = data;

• return 1;

• end procedure
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 −


• 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 3 − Increment front pointer to point to the next available
data element.
• Step 5 − Return success.
Dequeue Operation
Algorithm for dequeue operation
• procedure dequeue

• if queue is empty

• return underflow

• end if

• data = queue[front]

• front ← front + 1

• return true

• end procedure
Example
• int dequeue()

• {

• if(isempty())

• return 0;

• int data = queue[front];

• front = front + 1;

• return data;

• }
circular queue
• A circular queue is a variation of the regular queue in which the last
position is connected back to the first position to form a circle. It
addresses several limitations of a linear queue
• Efficient Use of Space:
•Problem with Linear Queue: In a linear queue, once the queue
reaches its maximum size and elements are dequeued from the
front, the space is wasted. Even though there are free spaces at the
front, the queue cannot reuse them, leading to inefficient use of
memory.
•Solution in Circular Queue: In a circular queue, the last position is
connected back to the first position. So, when the rear pointer
reaches the end of the queue and there are empty spaces at the
front (due to dequeue operations), the rear pointer can wrap around
and start filling these spaces. This makes better use of available
space.
Working of Circular Queue

•The Front pointer points to the first element in the queue.

•The Rear pointer points to the last element in the queue.

•When an element is inserted, the rear is incremented. If the


rear reaches the end of the queue (i.e., rear == size-1), it
wraps around to the start (rear = 0), provided there is space.

•Similarly, when an element is dequeued, the front is


incremented. If the front reaches the end of the queue, it wraps
around to the start (front = 0).
Example

• Initial state:
Dequeue 10:
• [ _ , _ , _ , _ , _ ] (Empty queue) [ _, 20, 30, _ , _ ]
^front ^rear
• Enqueue 10:
• [10, _ , _ , _ , _ ] Enqueue 40, 50:
• [ _, 20, 30, 40, 50]
^front, ^rear
^front ^rear

• Enqueue 20: Enqueue 60 (wraps around):


• [10, 20, _ , _ , _ ] [60, 20, 30, 40, 50]
• ^front, ^rear ^rear ^front

Dequeue 20:
• Enqueue 30: [60, _, 30, 40, 50]
• [10, 20, 30, _ , _ ] ^rear ^front
• ^front, ^rear
Basic Operation
isFull:
•The queue is full if the rear is right behind the front,
which happens either when front == 0 && rear ==
SIZE - 1 (queue wraps around), or front == rear + 1
(queue wraps around).
•isEmpty:
•The queue is empty when both front and rear are set
to -1
•enqueue:
•Adds an element at the rear. If the queue is full, the
operation is denied. The rear is incremented circularly by
using the modulo operation rear= (rear + 1) % SIZE.
Operation
•dequeue:
•Removes the element at the front. If the
queue is empty, the operation is denied. The
front is incremented circularly by front= (front
+ 1) % SIZE.
•display:
•Displays all elements from the front to the
rear in circular order, considering the circular
nature of the queue.
Arithmetic Expression Evaluation
The stack organization is very effective in evaluating
arithmetic expressions. Expressions are usually represented
in what is known as Infix notation, in which each operator
is written between two operands (i.e., A + B). With this
notation, we must distinguish between ( A + B )*C and A +
( B * C ) by using either parentheses or some operator-
precedence convention. Thus, the order of operators and
operands in an arithmetic expression does not uniquely
determine the order in which the operations are to be
performed.
• 1. Polish notation (prefix notation) –
It refers to the notation in which the operator is placed before its two
operands. Here no parentheses are required, i.e.,
• +AB
Postfix
• 2. Reverse Polish notation(postfix notation) –
It refers to the analogous notation in which the
operator is placed after its two operands. Again, no
parentheses is required in Reverse Polish notation,
i.e.,
• AB+ Stack-organized computers are better suited for
post-fix notation than the traditional infix notation.
Thus, the infix notation must be converted to the
postfix notation. The conversion from infix notation
to postfix notation must take into consideration the
operational hierarchy.
There are 3 levels of precedence for 5 binary operators as given
below:

Highest : Exponentiation (^)


Next highest : Multiplication (*) and division (/)
Lowest : Addition (+) and Subtraction (-)
Example
Infix notation : (A-B)*[C/(D+E)+F]
Post-fix notation: AB- CDE +/F +*
Now we need to calculate the value of these arithmetic operations by using a
stack.
The procedure for getting the result is:
• Convert the expression in Reverse Polish notation( post-fix notation).
• Push the operands into the stack in the order they appear.
• When any operator encounters then pop two topmost operands for
executing the operation.
• After execution push the result obtained into the stack.
• After the complete execution of expression, the final result remains on the
top of the stack.
• For example –
• Infix notation: (2+4) * (4+6)
• Post-fix notation: 2 4 + 4 6 + *
• Result: 60
The stack operations for this expression
evaluation is shown below:
Scanned Symbol Stack
2 2
4 2,4
+ 6
4 6,4
6 6,4,6
+ 6,10
* 60
Transforming Infix To Postfix Expression:
Q: Input
P:Output
1. Push “(“ onto stack, and “)” to the end of Q.
2. Scan Q from left to right and repeat step 3 to 6 for each element if Q untill the stack is
empty.
3. If an operand is encountered, add it to P.
4. If a left parenthesis is encountered, push it onto STACK.
5.If an operator @ (+,_,*,/) is encountered, then
a) Repeatedly POP from STACK and add to P each operator (On the Top of the stack) which has the same
precedence as or higher precedence than @
b) Add @ to STACK.
[End of if structure]

6.If a right parenthesis is encountered, then


c) Repeatedly POP from the STACK and add to P each operator(On the Top of the stack) until a left
parenthesis is encountered.
d) Remove the left parenthesis.
e) [End of IF structure]
7.Exit.
Infix to postfix

1.Initialize an empty stack S and an empty output list P for the


postfix expression.
2.Scan the infix expression E from left to right for each token:
•If the token is an operand (e.g., A, B, C):
•Append it to the output list P.
•If the token is a left parenthesis “(“:
•Push it onto the stack S.
•If the token is a right parenthesis ):
•Pop from the stack S to the output list P until a left parenthesis
“(“ is encountered. Discard the left parenthesis.
Infix to postfix
•If the token is an operator (e.g., +, -, *, /, ^):
•While there is an operator at the top of the stack with
greater than or equal precedence and the operator at
the
top of the stack is not a left parenthesis (, pop it to the
output
list P.
•Push the current operator onto the stack S.
3.After scanning the expression, pop all the operators
from the stack to the output list P
Example
• A+B*(C^D-E)^(F+G*H)–I
• Output:A B C D ^ E - F G H * + ^ * + I -
Token Action Output (P) Stack (S)
A Operand → Add to output A []
+ Operator → Push to stack A ['+']
B Operand → Add to output AB ['+']
Operator → Push to stack
* (higher precedence)
AB ['+', '*']
Left parenthesis → Push to
( stack AB ['+', '*', '(']
C Operand → Add to output ABC ['+', '*', '(']
^ Operator → Push to stack ABC ['+', '*', '(', '^']
D Operand → Add to output ABCD ['+', '*', '(', '^']
Operator → Pop ^ to output,
- then push - ABCD^ ['+', '*', '(', '-']
E Operand → Add to output ABCD^E ['+', '*', '(', '-']
Right parenthesis → Pop to
) output until ( ABCD^E- ['+', '*']
^

H
Operand → Add
F ABCD^E-F ['+', '*', '^', '(']
to output
Operator → Push
+ ABCD^E-F ['+', '*', '^', '(', '+']
to stack
Operand → Add
G ABCD^E-FG ['+', '*', '^', '(', '+']
to output
Operator → Push ['+', '*', '^', '(', '+',
* ABCD^E-FG
to stack '*']
Operand → Add ['+', '*', '^', '(', '+',
H ABCD^E-FGH
to output '*']
Right parenthesis
ABCD^E-FGH
) → Pop to output ['+', '*', '^']
*+
until (
Operator → Pop ^ A B C D ^ E - F G H
- ['-']
and *, then push - * + ^ *
Operand → Add ABCD^E-FGH
I ['-']
to output *+^*I
Pop remaining
ABCD^E-FGH
(end) operators to []
*+^*I-
output
Q:A+(B*C-(D/E^F)*G)*H
Book:Data Structure By Seymour Lipschutz
Example: 6.6
Ans.A B C * D E F ^ / G * - H * +
Infix to prefix
• The idea is to first reverse the given infix
expression while swapping ‘(‘ with ‘)’ and vice
versa, then convert this modified expression to
postfix notation using a stack-based approach
that follows operator precedence and associativity
rules, and finally reverse the obtained postfix
expression to get the prefix notation.
Step by step approach:

1.Reverse the infix expression. Note while reversing


each ‘(‘ will become ‘)’ and each ‘)’ becomes ‘(‘.
2.Convert the reversed infix expression to postfix
expression.
• Initialize an empty stack to store operators and
an empty string for the postfix expression.
• Scan the infix expression from left to right.
• If the character is an operand, append it to the
postfix expression.
• If the character is ‘(‘, push it onto the stack.
• If the character is ‘)’, pop from the stack and
append to the postfix expression until ‘(‘ is found,
then pop ‘(‘ without appending.

• If the character is an operator, pop and append


operators from the stack until the stack is empty
or a lower precedence operator is found, then
push the current operator onto the stack.
• After scanning the expression, pop and append
all remaining operators from the stack to the
postfix expression.
3.Reverse the postfix expression and return it.

You might also like