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

CSE 203-July2021-Stack-II

The document discusses the implementation and management of stacks using arrays, focusing on how to handle scenarios when the stack reaches its maximum capacity. It explains various strategies for increasing array size and their implications on performance, particularly amortized time complexity. Additionally, it introduces Reverse-Polish notation as a practical application of stacks in parsing mathematical expressions.

Uploaded by

rkiriyama5094
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 views72 pages

CSE 203-July2021-Stack-II

The document discusses the implementation and management of stacks using arrays, focusing on how to handle scenarios when the stack reaches its maximum capacity. It explains various strategies for increasing array size and their implications on performance, particularly amortized time complexity. Additionally, it introduces Reverse-Polish notation as a practical application of stacks in parsing mathematical expressions.

Uploaded by

rkiriyama5094
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/ 72

CSE 203: Data Structures

Elementary Data Structures- Stacks


Part II

1
Question…
• What happens if our guess of maxSize (in the
array based stack) is wrong?
– Throw an exception (What is this?)
– Ignore the object being pushed onto the stack
(Being an Ostrich?)
– Put the process pushing the object onto the stack
to sleep until another process removes the top of
the stack (Some advanced topic)
– We could increase the size of the array

2
Array Capacity
C
S
First, let us visualize what must occur to E
count = 8 -
allocate new memory array_capacity = 8 B
array U
C E
S T
E
-
B
U
E
T

3
Array Capacity
First, this requires a call to new Type[N] temp
where N is the new capacity
– We must have access to this so we must
store the address returned by new in a
local variable, say tmp count = 8
array_capacity = 8
array
C
S
E
-
B
U
E
T

4
Array Capacity
count = 8
array_capacity = 8 temp
Next, the values must array
C C
be copied over S S
E E
- -
B B
U U
E E
T T

5
Array Capacity
count = 8
array_capacity = 8 temp
array
The memory for the C C
original array must be S
E
S
E
deallocated - -
B B
U U
E E
T T

6
Array Capacity
count = 8
array_capacity = 8 temp
array
Finally, the appropriate C
member variables must S
E
be reassigned -
B
U
E
T

7
Array Capacity
Back to the original question:
– How much do we change the capacity?
– Add a constant?
– Multiply by a constant?

First, we recognize that any time that we push onto a


full stack, this requires n copies and the run time is
Q(n)

Therefore, push is usually Q(1) except when new


memory is required
8
Array Capacity
We will introduce the concept of amortized
time:
– If n operations requires Q(f(n)), we will say
that an individual operation has an amortized
run time of Q(f(n)/n)
– Therefore, if inserting n objects requires:
• Q(n2) copies, the amortized time is Q(n)
• Q(n) copies, the amortized time is Q(1)

9
Array Capacity
Let us consider the case of increasing the
capacity by 1 each time the array is full
– With each insertion when the array is full, this
requires all entries to be copied

10
Array Capacity
Suppose we double the
number of entries each
time the array is full
– Now the number of
copies appears to be
significantly
fewer

11
Array Capacity
Suppose we increase the array size by 1 each time it is full:
Suppose we insert k objects
– The pushing of the kth object on the stack requires k-1 copies
– The total number of copies is now given by:
n  n 
 
(k  1) 

k n 

n(n  1)
2
 n
n(n  1)
2
 
 n 2
k 1  k 1 
– Therefore, the amortized number of copies
is given by
 n2 
  n 
n 
– Therefore each push must run in
Q(n) time
– No wasted space.

12
Array Capacity
Suppose we double the array size each time it is full:
– We must make 1, 2, 4, 8, 16, 32, 64,... Copies at the 2nd, 3rd, 5th,
9th, 17th, 33rd, 65th, … insertions
– Inserting n objects would therefore require 1, 2, 4, 8, ..., all the
way up to the largest 2k < n copies or k  lg(n)
 lg( n ) 


k 0
2k 2 
lg( n )  1
1

2lg( n ) 1  1 2lg( n ) 21  1 2n  1  n 

– Therefore the amortized number of


copies per insertion is Q(1)
– The wasted space,
however is O(n)

13
Array Capacity
What if we increase the array size by a
larger constant?
– For example, increase the array size by 4, 8,
100?

14
Array Capacity
• Here we view the number of copies required when
increasing the array size by 4; however, in general,
suppose we increase it by a constant value m
– At first instance, number of copies = 4 (i.e., m)
– At second instance, number of copies = 4 x 2 = 8 (2m)
– At third instance, number of copies = 4 x 3 = 12 (3m)
– … n n
 
n/m n/m   1 2

 
mk m k 
mm  n
2

n
  n 2
2m 2
 
k 1 k 1

Therefore, the amortized


run time per
insertion is Q(n)

15
Array Capacity
Note the difference in worst-case amortized
scenarios:
Copies per Unused
Insertion Memory
(amortized)
Increase by 1 n–1 0
Increase by m n/m m–1
Increase by a factor of 2 1 n
Increase by a factor of r > 1 1/(r – 1) (r – 1)n

16
Stack Application: Reverse-Polish
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

17
Reverse-Polish Notation
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 –
(3 + 4) × 5 – 6 = 29
7 5 × 6 –
35 6 –
29
18
Reverse-Polish Notation
This is called reverse-Polish notation after
the mathematician Jan Łukasiewicz

http://www.audiovis.nac.gov.pl/

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

23 6 –
17
3 4 5 6 – × +
3 4 –1 × + 3 + 4 × (5 – 6) = –1
3 –4 +
–1
20
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

21
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

22
Reverse-Polish Notation
Evaluate the following reverse-Polish
expression using a stack:
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

23
Reverse-Polish Notation
Push 1 onto the stack
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

1
24
Reverse-Polish Notation
Push 1 onto the stack
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

2
1
25
Reverse-Polish Notation
Push 3 onto the stack
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

3
2
1
26
Reverse-Polish Notation
Pop 3 and 2 and push 2 + 3 = 5
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

5
1
27
Reverse-Polish Notation
Push 4 onto the stack
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

4
5
1
28
Reverse-Polish Notation
Push 5 onto the stack
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

5
4
5
1
29
Reverse-Polish Notation
Push 6 onto the stack
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

6
5
4
5
1
30
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
31
Reverse-Polish Notation
Pop 30 and 4 and push 4 – 30 = –26
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

–26
5
1
32
Reverse-Polish Notation
Push 7 onto the stack
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

7
–26
5
1
33
Reverse-Polish Notation
Pop 7 and –26 and push –26 × 7 = –182
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

–182
5
1
34
Reverse-Polish Notation
Pop –182 and 5 and push –182 + 5 = –177
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

–177
1
35
Reverse-Polish Notation
Pop –177 and 1 and push 1 – (–177) = 178
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

178
36
Reverse-Polish Notation
Push 8 onto the stack
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

8
178
37
Reverse-Polish Notation
Push 1 onto the stack
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

9
8
178
38
Reverse-Polish Notation
Pop 9 and 8 and push 8 × 9 = 72
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

72
178
39
Reverse-Polish Notation
Pop 72 and 178 and push 178 + 72 = 250
1 2 3 + 4 5 6 × – 7 × + – 8 9 × +

250
40
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
41
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 × +
42
Application: Parsing
Most parsing uses stacks

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

43
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
different context.

44
Parsing XHTML
A markup language is a means of
annotating a document to give 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
45
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>

46
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
• If it matches, the top of the stack is popped.
• If it does not, the XHTML is invalid.

47
Parsing XHTML
• Consider the code for How are you?
– <i>How <u>are</i> you</u>? **INVALID**
• The proper way to code this would be
– <i>How <u>are</u></i><u> you</u>?
• The justification for this is that now a stack
may be used to parse XML

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

<html>

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

<html> <head>

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

<html> <head> <title>

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

<html> <head> <title>

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

<html> <head>

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

<html> <body>

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

<html> <body> <p>

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

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

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

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

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

<html> <body> <p>

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

<html> <body>

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

<html>

60
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
61
HTML
Old HTML required neither closing tags nor
nesting
<html>
<head><title>Hello</title></head>
<body><p>This is a list of topics:
<ol> <!-- para ends with start of list -->
<li><i>veni <!-- implied </li> -->
<li>vidi <!-- italics continues -->
<li>vici</i>
</ol> <!-- end-of-file implies </body></html> -->

Parsers were therefore specific to HTML


– Results: ambiguities and inconsistencies
62
XML
XHTML is an implementation of XML

XML defines a class of general-purpose


eXtensible Markup Languages designed for
sharing information between systems

The same rules apply for any flavour of XML:


– opening and closing tags must match and be
nested
63
Computing Spans
7
• We show how to use a stack as 6
an auxiliary data structure in an 5
algorithm
4
• Given an an array X, the span
S[i] of X[i] is the maximum 3
number of consecutive 2
elements X[j] immediately 1
preceding X[i] and such that 0
X[j]  X[i]
• 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
64
Algorithm I
Algorithm spans1(X, n)
Input array X of n integers
Output array S of spans of X
S  new array of n integers
for i  0 to n  1 do
s1
while s  i  X[i - s]  X[i]
ss+1
S[i]  s
return S
65
Algorithm I: Analysis
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 loops n times
s1 n
while s  i  X[i - s]  X[i] 1 + 2 + …+ (n  1) (in total)
ss+1 1 + 2 + …+ (n  1) (in total)
S[i]  s n
return S 1

Algorithm spans1 runs in O(n2) time

66
Computing Spans with a Stack
• We keep in a stack the
7
indices of the elements
6
visible when “looking back”
5
• We scan the array from left
4
to right
– Let i be the current index 3
– We pop indices from the 2
stack until we find index j 1
such that X[i]  X[j]
0
– We set S[i]  i - j
– We push i onto the stack
0 1 2 3 4 5 6 7

67
Algorithm II
Algorithm spans2(X, n)

S  new array of n integers


A  new empty stack

for i  0 to n  1 do

while (A.isEmpty() 

X[top()]  X[i] ) do
j  A.pop()

if A.isEmpty() then
68
Algorithm II: Analysis
Each index of the array Algorithm spans2(X, n)
 Is pushed into the
stack exactly one
S  new array of n integers
 Is popped from the
stack at most once
The statements in the A  new empty stack
while-loop are executed
at most n times for i  0 to n  1 do
Algorithm spans2 runs in
O(n) time
while
(A.isEmpty() 

X[top()]  X[i] ) do

j
A.pop() 69
A Problem
• Suppose you have a linked list L
• Problem: Find the 3rd node before the one
containing G.
• Can you propose a solution?

70
Solution 1: Link Inversion
• As we walk down the list with two pointers P,
Q, we reverse the NEXT pointers to point to
the previous node:

71
Solution 2: Use Stack
• Walk down the list, pushing node addresses
onto a stack.
• When you find “G”, pop 3 addresses off the
stack.

72

You might also like