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

L5_Stack_Queue

The document discusses stacks and queues, focusing on stack operations such as push, pop, and peek, along with their applications in parsing code, tracking function calls, and managing undo/redo operations. It explains the last-in-first-out (LIFO) behavior of stacks, their implementation using arrays or linked lists, and provides examples of stack usage in algorithms like the Stock Span Problem and parentheses matching. Additionally, it highlights the performance and limitations of stacks, emphasizing their importance in various programming scenarios.

Uploaded by

rounak15jais24
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views

L5_Stack_Queue

The document discusses stacks and queues, focusing on stack operations such as push, pop, and peek, along with their applications in parsing code, tracking function calls, and managing undo/redo operations. It explains the last-in-first-out (LIFO) behavior of stacks, their implementation using arrays or linked lists, and provides examples of stack usage in algorithms like the Stock Span Problem and parentheses matching. Additionally, it highlights the performance and limitations of stacks, emphasizing their importance in various programming scenarios.

Uploaded by

rounak15jais24
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 127

Stack & Queue

Applications
Numerous applications:
 Parsing code:
 Matching parenthesis
 XML (e.g., XHTML)
 Tracking function calls
 Dealing with undo/redo operations
 Reverse-Polish calculators
 Assembly language

 The stack is a very simple data structure


 Given any problem, if it is possible to use a stack, this significantly
simplifies the solution
Abstract Stack
Also called a last-in–first-out (LIFO) behaviour
* Graphically, we may view these operations as follows:

There are two exceptions associated with abstract stacks:


* It is an undefined operation to call either pop or top on an empty stack
Concepts of Stacks
• A stack is a linear data structure with the property that
the elements in a stack are added (push) and removed
(pop) only from one end (top)

• A stack is called a LIFO (Last-In First-Out) data


structure as the element that is inserted last is the first
one to be taken out

• Stacks can be implemented either using an array or a


linked list
Stack Operations
1. Push – add an element to a stack

2. Pop -- remove the top element from stack,


return or not return the data of top element

3. Peek – get the data of top element of stack,


return the value of the top element

All operations work at the top of a stack


2. Array Representation of Stacks
• Use an element array of MAX size to represent a stack.
• Use a variable TOP to represent the index/or address of
the top element of the stack in the array. It is this
position from where the element will be added or
removed
• TOP = -1 indicates that the stack is empty
• TOP = MAX -1 indicates that the stack is full
Push Operation
• The push operation is used to insert an element in to the stack.
• The new element is added at the topmost position of the stack.
• First check if TOP==MAX-1.
If true, then it means the stack is full and no more insertions can
further be added, an OVERFLOW message is printed.
• If not true, increase TOP by 1, then add the element at TOP position

A B C D E

0 1 2 3 TOP = 4 5 6 7 8 9

A B C D E F

0 1 2 3 4 TOP =5 6 7 8 9
Pop Operation
• The pop operation is used to delete the topmost element from the
stack.
• First check if TOP == -1.
If true then it means the stack is empty so no more deletions can
further be done, an UNDERFLOW message is printed.
If not true, get the value of the top element, decrease TOP by one.

A B C D E

0 1 2 3 TOP = 4 5 6 7 8 9

A B C D

0 1 2 TOP = 3 4 5 6 7 8 9
Peek Operation
• Peek is an operation that returns the value of the topmost
element of the stack without deleting it from the stack.
• he peep operation first checks if the stack is empty or contains
some elements.
• If TOP == -1, then an appropriate message is printed else the
value is returned.
A B C D E

0 1 2 3 TOP = 4 5 6 7 8 9

Here Peep operation will return E, as it is the value of the


topmost element of the stack.
*Stack *Queue
* Basic principles * Basic principles
* Operation of stack * Operation of queue
* Stack using Array * Queue using Array
* Stack using Linked List * Queue using Linked List
* Applications of stack * Applications of queue
STACK: Last-In-First-Out (LIFO)
• void push (stack *s, int element);
/* Insert an element in the stack */
• int pop (stack *s);
/* Remove and return the top element */
• void create (stack *s);
/* Create a new stack */
• int isempty (stack *s);
/* Check if stack is empty */
• int isfull (stack *s);
/* Check if stack is full */

Assumption: stack contains integer elements!


Stack using Array
Knowing your Computer Stack

ulimit –s
ulimit –a

ulimit -s <new_size_in_kb>
pmap pid
PUSH-Operation

PUSH

top
top
POP

POP

top
top
Stack using Linked List
Push using Linked List

PUSH OPERATION

top
Stack
Operation
Pop using Linked List

POP OPERATION

top
Basic Idea
• In the array implementation, we would:
• Declare an array of fixed size (which determines the maximum
size of the stack).

• Keep a variable which always points to the “top” of the stack.


• Contains the array index of the “top” element.
• In the linked list implementation, we would:
• Maintain the stack as a linked list.
• A pointer variable top points to the start of the list.
• The first element of the linked list is considered as the stack top.
Declaration

#define MAXSIZE 100 struct lifo


{
struct lifo int value;
{ struct lifo *next;
int st[MAXSIZE]; };
int top; typedef struct lifo stack;
};
typedef struct lifo stack; stack *top;
stack s;

ARRAY LINKED LIST


Stack Creation

void create (stack *s) void create (stack **top)


{ {
s->top = -1; *top = NULL;
/* s->top points to /* top points to NULL,
last element indicating empty
pushed in; stack */
initially -1 */ }
}

ARRAY LINKED LIST


Pushing an element into stack

void push (stack *s, int element) void push (stack **top, int element)
{ {
stack *new;
if (s->top == (MAXSIZE-1))
{ new = (stack *)malloc (sizeof(stack));
printf (“\n Stack overflow”); if (new == NULL)
exit(-1); {
} printf (“\n Stack is full”);
exit(-1);
else
}
{
s->top++; new->value = element;
s->st[s->top] = element; new->next = *top;
} *top = new;
}
}

ARRAY LINKED LIST


Popping an element from stack

int pop (stack **top)


{
int pop (stack *s) int t;
{ stack *p;
if (s->top == -1) if (*top == NULL)
{ {
printf (“\n Stack underflow”); printf (“\n Stack is empty”);
exit(-1);
exit(-1); }
} else
else {
{ t = (*top)->value;
p = *top;
return (s->st[s->top--]); *top = (*top)->next;
} free (p);
} return t;
}
}

ARRAY LINKED LIST


Checking for stack empty

int isempty (stack *s) int isempty (stack *top)


{ {
if (s->top == -1) if (top == NULL)
return 1; return (1);
else else
return (0); return (0);
} }

ARRAY LINKED LIST


Checking for Stack Full

int isempty (stack *s) int isempty (stack *top)


{ {
if (s->top == -1) if (top == NULL)
return 1; return (1);
else else
return (0); return (0);
} }

ARRAY LINKED LIST


Example: A Stack using an Array
#include <stdio.h>
#define MAXSIZE 100
struct lifo
{
int st[MAXSIZE];
int top;
};
typedef struct lifo stack;
main() {
stack A, B;
create(&A);
create(&B);
push(&A,10);
push(&A,20);
push(&A,30);
push(&B,100);
push(&B,5);
printf (“%d %d”, pop(&A), pop(&B));
push (&A, pop(&B));
if (isempty(&B))
printf (“\n B is empty”);
return;
}
Example: A Stack using Linked List
#include <stdio.h>
struct lifo
{
int value;
struct lifo *next;
};
typedef struct lifo stack;
main() {
stack *A, *B;
create(&A);
create(&B);
push(&A,10);
push(&A,20);
push(&A,30);
push(&B,100);
push(&B,5);
printf (“%d %d”, pop(&A), pop(&B));
push (&A, pop(&B));
if (isempty(B))
printf (“\n B is empty”);
return;
}
Performance and Limitations
 Performance
 Let n be the number of elements in the stack
 The space used is O(n)
 Each operation runs in time O(1)
 Limitations
 The maximum size of the stack must be defined a
priori and cannot be changed
 Trying to push a new element into a full stack
causes an implementation-specific exception
Applications of Stacks
• Direct applications:
• Page-visited history in a Web browser
• Undo sequence in a text editor
• Chain of method calls in the Java Virtual Machine
• Validate XML

• Indirect applications:
• Auxiliary data structure for algorithms
• Component of other data structures
The Stock Span Problem
(given stock prices, day wise time series data)

Eg. Auxiliary data structure for algorithms


Computing Spans
7
 Using a stack as an auxiliary
6
data structure in an algorithm
5
 Given an an array X, the span
4
S[i] of X[i] is the maximum
number of consecutive
3
elements X[j] immediately 2
preceding X[i] and such that 1
X[j]  X[i] 0
 Spans have applications to 0 1 2 3 4
financial analysis
 E.g., stock at 52-week high X 6 3 4 5 2
S 1 1 2 3 1
Computing Spans
Quadratic Algorithm
Algorithm spans1(X, n)
Input array X of n integers
Output array S of spans of X #
S  new array of n integers n
for i  0 to n  1 do n
s0 n
while s  i  X[i  s]  X[i] 1 + 2 + …+ (n  1)
ss+1 1 + 2 + …+ (n  1)
S[i]  s n
return S 1

Algorithm spans1 runs in O(n2) time


Computing Spans with a Stack
 We keep in a stack the 7
indices of the elements
6
visible when “looking
back” 5
4
 We scan the array from
left to right 3
 Let i be the current index 2
 We pop indices from the 1
stack until we find index j 0
such that X[i]  X[j]
0 1 2 3 4 5 6 7
 We set S[i]  i  j
 We push x onto the stack
Linear Algorithm
Each index of the Algorithm spans2(X, n) #
array S  new array of n integers n
 Is pushed into the A  new empty stack 1
stack exactly one for i  0 to n  1 do n
 Is popped from while (A.isEmpty() 
the stack at most
X[A.top()]  X[i] ) do n
once
A.pop() n
The statements in if A.isEmpty() then n
the while-loop are S[i]  i + 1 n
executed at most else
n times S[i]  i  A.top() n
Algorithm spans2 A.push(i) n
runs in O(n) time return S 1
Parentheses Matching
 Each “(”, “{”, or “[” must be paired with
a matching “)”, “}”, or “[”
 correct: ( )(( )){([( )])}
 correct: ((( )(( )){([( )])}
 incorrect: )(( )){([( )])}
 incorrect: ({[ ])}
 incorrect: (
Application: Parsing

Most parsing uses stacks

Examples includes:
– Matching tags in XHTML
– In C++, matching
• parentheses ( ... )
• brackets, and [ ... ]
• braces { ... }
Parsing XHTML

The first example will demonstrate parsing XHTML

We will show how stacks may be used to parse an XHTML


document

You will use XHTML (and more generally XML and other markup
languages) in the workplace
Parsing XHTML

A markup language is a means of annotating a document to given


context to the text
– The annotations give information about the structure or presentation of
the text

The best known example is HTML, or HyperText Markup Language


– We will look at XHTML
Parsing XHTML

XHTML is made of nested


– opening tags, e.g., <some_identifier>, and
– matching closing tags, e.g., </some_identifier>
<html>
<head><title>Hello</title></head>
<body><p>This appears in the <i>browser</i>.</p></body>
</html>
Parsing XHTML
Nesting indicates that any closing tag must match the most recent
opening tag

Strategy for parsing XHTML:


– read though the XHTML linearly
– place the opening tags in a stack
– when a closing tag is encountered, check that it matches what is on top
of the stack and
Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html>
Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <head>
Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <head> <title>


Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <head> <title>


Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <head>
Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <body>
Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <body> <p>


Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <body> <p> <i>


Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <body> <p> <i>


Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <body> <p>


Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html> <body>
Parsing XHTML

<html>
<head><title>Hello</title></head>
<body><p>This appears in the
<i>browser</i>.</p></body>
</html>

<html>
Parsing XHTML

We are finished parsing, and the stack is empty

Possible errors:
– a closing tag which does not match the opening tag on top of the stack
– a closing tag when the stack is empty
– the stack is not empty at the end of the document
Parsing C

Like opening and closing tags, C parentheses, brackets, and braces


must be similarly nested:

void initialize( int *array, int n ) {


for ( int i = 0; i < n; ++i ) {
array[i] = 0;
}
}
Balanced Expressions
Balanced Expressions

Checking for Balanced Balanced Not Balanced


Expressions { [ ( ) ( ) ] ( ) } [ ( ] )
Scan expression:
Ignore characters that are not
delimiters
a {{ b [[ c (( d + e ) / 2 - f ] + 1 }
When open delimiter is encountered
push it on the stack
When close delimiter is encountered
check to see if it matches top of stack
if yes, pop off top of stack
if not, expression is not balanced
If braces are balanced
stack is empty when expression is
done delimeterStack
Balanced Expressions

Checking for Balanced Balanced Not Balanced


Expressions { [ ( ) ( ) ] ( ) } [ ( ] )
Scan expression:
Ignore characters that are not
delimiters
a {{ b [[ c (( d + e ] / 2 - f ) + 1 }
When open delimiter is encountered
push it on the stack
When close delimiter is encountered
check to see if it matches top of stack
if yes, pop off top of stack
if not, expression is not balanced
If braces are balanced
stack is empty when expression is
done
Algebraic Expressions
Algebraic Expressions

Operator Precedence Infix


() Parenthesis
Common Notation
5 + 6
20 - 16
4 2 * 8
2 ^ 3
-+ Unary 5 + 6 * 7
^ Exponentiation (5 + 6) * 7 5 + 6* 7
* / % Multiplicative
+- Additive
Prefix 5 + 6* 7
Functional Languages
Binary Operators + 5 6
Require two + * 7 6 5
operands * + 5 6 7
4+5 Postfix
Unary Operators Reverse Polish Notation
5 6 +
Single
5 6 7 * +
operand
7 5 6 + *
-6

operatorStack
Evaluating Postfix Expressions

Scan characters in the Postfix Expression Postfix


When an operand is encountered, 5 4 2 + 3 ^ *

push it onto the operandStack


6
216
When an operator is encountered,
1080
apply it to the top two operands
of the operandStack
pop the operands from
the operandStack
push the result of the operation
onto the operandStack

operandStack
Infix and Postfix Notations
• Infix: operators placed between operands:
A+B*C
• Postfix: operands appear before their operators:-
ABC*+
• There are no precedence rules to learn in postfix notation, and parentheses
are never needed
Infix notation
Normally, mathematics is written using what we call in-fix notation:
(3 + 4) × 5 – 6
The operator is placed between to operands

One weakness: parentheses are required


(3 + 4) × 5 – 6 = 29
3+4 × 5–6 = 17
3 + 4 × (5 – 6) = –1
(3 + 4) × (5 – 6) = –7
Postfix
Alternatively, we can place the operands first, followed by the
operator:
(3 + 4) × 5 – 6
3 4 + 5 × 6 –

Parsing reads left-to-right and performs any operation on the


last two operands:
3 4 + 5 × 6 –
7 5 × 6 –
35 6 –
29
Reverse-Polish Notation

This is called reverse-Polish notation after the mathematician Jan


Łukasiewicz

He also made significant contributions to


logic and other fields

http://www.audiovis.nac.gov.pl/
Infix to Postfix Rules
Current Operator Postfix string
Expression: symbol Stack
1 A A
A * (B + C * D) + E 2 * * A
3 ( *( A
becomes
4 B *( AB
ABCD*+*E+ 5 + *(+ AB
6 C *(+ ABC
7 * *(+* ABC
8 D *(+* ABCD
Postfix notation
is also called as 9 ) * ABCD*+
Reverse Polish 10 + + ABCD*+*
Notation (RPN) 11 E + ABCD*+*E
12 ABCD*+*E+
Prefix Notation
• In a prefix notation, the operator is placed before the operands.
• For example, if A+B is an expression in infix notation, then the
corresponding expression in prefix notation is given by +AB.
• While evaluating a prefix expression, the operators are applied to
the operands that are present immediately on the right of the
operator.
• Prefix expressions also do not follow the rules of operator
precedence, associativity, and even brackets cannot alter the
order of evaluation.
• The expression (A + B) * C is written as:
*+ABC in the prefix notation
Evaluation of an Infix Expression
STEP 1: Convert the infix expression into its equivalent postfix expression
Algorithm to convert an Infix notation into postfix notation
Step 1: Add ‘)” to the end of the infix expression
Step 2: Push “(“ on to the stack
Step 3: Repeat until each character in the infix notation is scanned
IF a “(“ is encountered, push it on the stack
IF an operand (whether a digit or an alphabet) is encountered,
add it to the postfix expression.
IF a “)” is encountered, then;
a. Repeatedly pop from stack and add it to the postfix expression until a “(” is
encountered.
b. Discard the “(“. That is, remove the “(“ from stack and do not
add it to the postfix expression
IF an operator X is encountered, then;
a Repeatedly pop from stack and add each operator (popped from the stack) to the
postfix expression which has the same precedence or a higher precedence than X
b. Push the operator X to the stack
Step 4: Repeatedly pop from the stack and add it to the postfix expression
until the stack is empty
Step 5: EXIT
Evaluation of an Infix Expression
• Step 1 infix “(9 - (( 3 * 4) + 8) / 4)" => postfix “9 3 4 * 8 + 4 / -“

infix Stack postfix


( (
9 ( 9
- (- 9
( (-( 9
( (-(( 9
3 (-(( 93
* (-((* 93
4 (-((* 934
) (-( 934*
+ (-(+ 934*
8 (-(+ 934*8
) (- 934*8+
/ (-/ 934*8+
4 (-/ 934*8+4
) 934*8+4/-
Evaluation of an Infix Expression
STEP 2: Evaluate the postfix expression

Algorithm to evaluate a postfix expression

Step 1: Add a “)” at the end of the postfix expression


Step 2: Scan every character of the postfix expression and
repeat
steps 3 and 4 until “)”is encountered
Step 3: IF an operand is encountered, push it on the stack
IF an operator X is encountered, then
a. pop the top two elements from the stack as A and B
b. Evaluate B X A, where A was the topmost element
and B was
the element below A.
c. Push the result of evaluation on the stack
[END OF IF]
Step 4: SET RESULT equal to the topmost element of the stack
Step 5: EXIT
Evaluation of an Infix Expression
• Example: evaluate “9 - (( 3 * 4) + 8) / 4”.
• Step 1 infix “(9 - (( 3 * 4) + 8) / 4)" => postfix “9 3 4 * 8 + 4 / -“
• Step 2 evaluate “9 3 4 * 8 + 4 / -“
infix Stack postfix
( ( Character
Stack
9 ( 9 scanned
- (- 9 9 9
( (-( 9
3 9, 3
( (-(( 9
3 (-(( 93 4 9, 3, 4

* (-((* 93 * 9, 12
4 (-((* 934
8 9, 12, 8
) (-( 934*
+ 9, 20
+ (-(+ 934*
8 (-(+ 934*8 4 9, 20, 4
) (- 934*8+ / 9, 5
/ (-/ 934*8+
- 4
4 (-/ 934*8+4
) 934*8+4/-
Example
(5*(((9+8)*(4*6))+7))
• Input
598+46**7+*
• Evaluation
push(5)
push(9)
push(8)
push(pop() + pop())
push(4)
push(6)
push(pop() * pop())
push(7)
push(pop() + pop())
push(pop() * pop())
print(pop())
• What is the answer?
Reverse-Polish Notation

Other examples:
3 4 5 × + 6 –
3 20 + 6 –
23 6 –
17
3 4 5 6 – × +
3 4 –1 × +
3 –4 +
–1
Reverse-Polish Notation

Benefits:
– No ambiguity and no brackets are required
– It is the same process used by a computer to perform computations:
• operands must be loaded into registers before operations can be performed
on them
– Reverse-Polish can be processed using stacks
Reverse-Polish Notation

Reverse-Polish notation is used with some programming languages


– e.g., postscript, pdf, and HP calculators

Similar to the thought process required for writing assembly


language code
– you cannot perform an operation until you have all of the operands
loaded into registers

MOVE.L #$2A, D1 ; Load 42 into Register D1


MOVE.L #$100, D2 ; Load 256 into Register D2
ADD D2, D1 ; Add D2 into D1
Reverse-Polish Notation

The easiest way to parse reverse-Polish notation is to use an


operand stack:
– operands are processed by pushing them onto the stack
– when processing an operator:
• pop the last two items off the operand stack,
• perform the operation, and
• push the result back onto the stack
Reverse-Polish Notation

Evaluate the following reverse-Polish expression using a stack:


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +
Reverse-Polish Notation

Push 1 onto the stack


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

1
Reverse-Polish Notation

Push 1 onto the stack


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

2
1
Reverse-Polish Notation

Push 3 onto the stack


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

3
2
1
Reverse-Polish Notation

Pop 3 and 2 and push 2 + 3 = 5


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

5
1
Reverse-Polish Notation

Push 4 onto the stack


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

4
5
1
Reverse-Polish Notation

Push 5 onto the stack


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

5
4
5
1
Reverse-Polish Notation

Push 6 onto the stack


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

6
5
4
5
1
Reverse-Polish Notation

Pop 6 and 5 and push 5 × 6 = 30


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

30
4
5
1
Reverse-Polish Notation

Pop 30 and 4 and push 4 – 30 = –26


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

–26
5
1
Reverse-Polish Notation

Push 7 onto the stack


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

7
–26
5
1
Reverse-Polish Notation

Pop 7 and –26 and push –26 × 7 = –182


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

–182
5
1
Reverse-Polish Notation

Pop –182 and 5 and push –182 + 5 = –177


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

–177
1
Reverse-Polish Notation

Pop –177 and 1 and push 1 – (–177) = 178


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

178
Reverse-Polish Notation

Push 8 onto the stack


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

8
178
Reverse-Polish Notation

Push 1 onto the stack


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

9
8
178
Reverse-Polish Notation

Pop 9 and 8 and push 8 × 9 = 72


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

72
178
Reverse-Polish Notation

Pop 72 and 178 and push 178 + 72 = 250


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

250
Reverse-Polish Notation

Thus
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +
evaluates to the value on the top: 250
The equivalent in-fix notation is
((1 – ((2 + 3) + ((4 – (5 × 6)) × 7))) + (8 × 9))

We reduce the parentheses using order-of-operations:


1 – (2 + 3 + (4 – 5 × 6) × 7) + 8 × 9
Reverse-Polish Notation

Incidentally,
1 – 2 + 3 + 4 – 5 × 6 × 7 + 8 × 9 = – 132
which has the reverse-Polish notation of
1 2 – 3 + 4 + 5 6 7 × × – 8 9 × +

For comparison, the calculated expression was


1 2 3 + 4 5 6 × – 7 × + – 8 9 × +
Convert Infix Expression into Prefix
Expression
Consider an infix expression: (A – B / C) * (A / K – L)
• Step 1: Reverse the infix string. Note that while reversing the string
you must interchange left and right parenthesis.
(L – K / A) * (C / B – A)
• Step 2: Obtain the corresponding postfix expression of the infix
expression obtained as a result of Step 1.
• The expression is: (L – K / A) * (C / B – A)
• Therefore, [L – (K A /)] * [ (C B /) - A ]
= [LKA/-] * [ CB/A-]
=LKA/-CB/A-*
• Step 3: Reverse the postfix expression to get the prefix expression
• Therefore, the prefix expression is * - A / B C - / A K L
Ex.
Infix Postfix
A+B AB+
A+B*C ABC*+
(A + B) * C AB+C*
A+B*C+D ABC*+D+
(A + B) * (C + D) AB+CD+*
A*B+C*D AB*CD*+

A + B * C  (A + (B * C))  (A + (B C *) )  A B C * +

A + B * C + D  ((A + (B * C)) + D )  ((A + (B C*) )+ D) 


((A B C *+) + D)  A B C * + D +
Exercises
• (5 * (((9 + 8) * (4 * 6)) + 7))

Ans:598+46**7+*
• (6 * (5 + (2 + 3) * 8 + 3))
Ans: 6523+8*+3+*
• (a + b * c + (d * e + f) * g)
Ans: abc*+de*f+g*+
Standard Template Library

#include <iostream>
#include <stack>
using namespace std;
int main() {
stack<int> istack;

istack.push( 13 );
istack.push( 42 );
cout << "Top: " << istack.top() << endl;
istack.pop(); // no return value
cout << "Top: " << istack.top() << endl;
cout << "Size: " << istack.size() << endl;

return 0;
}
The Java Virtual Machine

*The Java Virtual Machine (JVM) main() {


keeps track of the chain of active int i = 5;
methods with a stack bar
foo(i);
*When a method is called, the JVM }
PC = 1
pushes on the stack a frame m=6
containing foo(int j) {
* Local variables and return value int k;
foo
* Program counter, keeping track of the PC = 3
statement being executed k = j+1; j=5
*When a method ends, its frame is bar(k); k=6
popped from the stack and control }
is passed to the method on top of main
the stack bar(int m) { PC = 2
*Allows for recursion … i=5
}
The algorithm steps
1. Print operands as they arrive.
2. If the stack is empty or contains a left parenthesis on top, push the incoming operator
onto the stack.
3. If the incoming symbol is a left parenthesis, push it on the stack.
4. If the incoming symbol is a right parenthesis, pop the stack and print the operators
until you see a left parenthesis. Discard the pair of parentheses.
5. If the incoming symbol has higher precedence than the top of the stack, push it on the
stack.
6. If the incoming symbol has equal precedence with the top of the stack, use association.
If the association is left to right, pop and print the top of the stack and then push the
incoming operator. If the association is right to left, push the incoming operator.
7. If the incoming symbol has lower precedence than the symbol on the top of the stack,
pop the stack and print the top operator. Then test the incoming operator against the
new top of stack.
8. At the end of the expression, pop and print all operators on the stack. (No parentheses
should remain.)
Queue
Organizing Data By Linear Position

Top Position List


Grocery List

1 Bread

2 Oranges
Front Back
3 Tortillas

Stack 4 Beans

5 Apples

6 Lettuce

7 Milk

Queue
ADT-Queue
Organizes entries in the order added
First-In, First-out (FIFO) Behavior
Entries are added at the back/rear
Removals occur at the front peekFront
Access restricted to entries dequeue enqueue
Only front entry is accessible
Earliest entry added to queue

front back(rear)
Queue Representation

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


lists, Pointers and Structures.
QUEUE: First-In-First-Out (LIFO)

void enqueue (queue *q, int element);


/* Insert an element in the queue */
int dequeue (queue *q);
/* Remove an element from the queue */
queue *create();
/* Create a new queue */
int isempty (queue *q);
/* Check if queue is empty */
int size (queue *q);
/* Return the no. of elements in queue */

Assumption: queue contains integer elements!


Queue using Linked List
Basic Idea
• Basic idea:
• Create a linked list to which items would be added to one end and
deleted from the other end.
• Two pointers will be maintained:
• One pointing to the beginning of the list (point from where
elements will be deleted).
• Another pointing to the end of the list (point where new
elements will be inserted). Rear

Front DELETION INSERTION


Queue using Linked List

ENQUEUE

front rear
Queue using Linked List

DEQUEUE

front rear
Example: Queue using Linked List

struct qnode
{
int val;
struct qnode *next;
};

struct queue
{
struct qnode *qfront, *qrear;
};
typedef struct queue QUEUE;

int peek(QUEUE *q) {


if (isEmpty(q)) {
printf("Queue is empty.
Nothing to peek.\n");
return -1;
}
return q->qfront->val;
}
Example: Queue using Linked List
void enqueue(QUEUE *q, int value) {
int size (QUEUE *q) struct qnode *newNode
{ newNode= (struct qnode *)malloc(sizeof(struct
queue *q1; qnode));
int count=0; if (!newNode) {
q1=q; printf("Memory allocation failed.\n");
while(q1!=NULL) return;
{ }
q1=q1->next; newNode->val = value;
count++; newNode->next = NULL;
}
return count; if (isEmpty(q)) {
} q->qfront = q->qrear = newNode;
} else {
q->qrear->next = newNode;
q->qrear = newNode;
}
printf("%d enqueued to queue.\n", value);
}
Example: Queue using Linked List

int dequeue(QUEUE *q) {


if (isEmpty(q)) {
printf("Queue is empty. Cannot
dequeue.\n");
return -1;
}

struct qnode *temp = q->qfront;


int dequeuedValue = temp->val;
q->qfront = q->qfront->next;

if (q->qfront == NULL) {
q->qrear = NULL;
}

free(temp);
return dequeuedValue;
}
Problem With Array Implementation

• The size of the queue depends on the number and order of enqueue
and dequeue.
• It may be situation where memory is available but enqueue is not
possible.
ENQUEUE DEQUEUE
Effective queuing storage area of array gets reduced.
0 N

front
front rearrear

Use of circular array indexing


ADT- Deque
An Abstract Deque (Deque ADT) is an abstract
data structure which emphasizes specific
operations:
* Insertions and removals are performed
individually
* Allows insertions at both the front and back of the
deque
ADT- Deque
The operations will be called
front back
push_front push_back
pop_front pop_back

There are four errors associated with this abstract data type:
* It is an undefined operation to access or pop from an empty deque
Deques
• A deque (double-ended queue) is a list in which
elements can be inserted or deleted at either end.
• Also known as a head-tail linked list because elements
can be added to or removed from the front (head) or
back (tail).
• A deque can be implemented either using a circular array
or a circular doubly linked list.
• In a deque, two pointers are maintained, LEFT and RIGHT
which point to either end of the deque.
Deque variants
• There are two variants of deques:
– Input restricted deque: In this dequeue insertions can be
done only at one of the ends while deletions can be done
from both the ends.
– Output restricted deque: In this dequeue deletions can be
done only at one of the ends while insertions can be done
on both the ends.

29 37 45 54 63

0 1 2 LEFT = 3 4 5 6 RIGHT = 7 8 9

63 27 18
42

RIGHT = 0 1 2 3 4 5 6 LEFT = 7 8 9
Priority Queues
• A priority queue is a queue in which each element is assigned a
priority.
• The priority of elements is used to determine the order in which
these elements will be processed.
• The general rule of processing elements of a priority queue can be
given as:
o An element with higher priority is processed before an element
with lower priority
o Two elements with same priority are processed on a first come
first served (FCFS) basis
• Priority queues are widely used in operating systems to execute the
highest priority process first.
• In computer’s memory priority queues can be represented using
arrays or linked lists.
Linked List Representation of Priority
Queues
• When a priority queue is implemented using a linked list, then
every node of the list contains three parts: (1) the information or
data part, (ii) the priority number of the element, (iii) and address
of the next element.
• If we are using a sorted linked list, then element having higher
priority will precede the element with lower priority.

A 1 B 2 C 3 D 3 E 4 X

Priority queue after insertion of a new node (F, 4)

A 1 B 2 C 3 D 3 E 4 F 4 X
Applications of Queues
1. Queues are widely used as waiting lists for a single
shared resource like printer, disk, CPU.

2. Queues are used to transfer data asynchronously


e.g., pipes, file IO, sockets.

3. Queues are used as buffers on MP3 players and


portable CD players, iPod playlist.
Applications of Queues
5. Queues are used in Playlist for jukebox to add songs to the
end, play from the front of the list.

6. Queues are used in OS for handling interrupts. When


programming a real-time system that can be interrupted,
for ex, by a mouse click, it is necessary to process the
interrupts immediately before proceeding with the current
job. If the interrupts have to be handled in the order of
arrival, then a FIFO queue is the appropriate data structure
• Indirect applications:-
• Auxiliary data structure for algorithms
• Component of other data structures
Applications of Queues
For example, in downloading files from web server, those requests
not currently being downloaded are
marked as “Queued”
Applications of Queues

File Search: We would search the more shallow directories


first then plunge deep into searching one sub-directory and all
of its contents
One such search is called a breadth-first traversal
* Search all the directories at one level before descending a level
Organizing Data By Linear Position

Top Position List


Grocery List

1 Bread

2 Oranges
Front Back
3 Tortillas

Stack 4 Beans

5 Apples

6 Lettuce

7 Milk

Queue

You might also like