0% found this document useful (0 votes)
26 views105 pages

3 02 Stacks

The document discusses stacks, which are a data structure that follows the last-in, first-out (LIFO) principle. It describes an abstract stack as a linear data structure that allows insertions and removals from one end only. Common applications of stacks include parsing code, tracking function calls, and implementing undo/redo operations. The document then covers two implementations of stacks: using singly linked lists and using arrays. Operations on the front of a linked list and the back of an array have optimal time complexity of O(1).

Uploaded by

Rubim Shrestha
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)
26 views105 pages

3 02 Stacks

The document discusses stacks, which are a data structure that follows the last-in, first-out (LIFO) principle. It describes an abstract stack as a linear data structure that allows insertions and removals from one end only. Common applications of stacks include parsing code, tracking function calls, and implementing undo/redo operations. The document then covers two implementations of stacks: using singly linked lists and using arrays. Operations on the front of a linked list and the back of an array have optimal time complexity of O(1).

Uploaded by

Rubim Shrestha
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/ 105

ECE 250 Algorithms and Data Structures

Stacks

Douglas Wilhelm Harder, M.Math. LEL


Department of Electrical and Computer Engineering
University of Waterloo
Waterloo, Ontario, Canada

ece.uwaterloo.ca
[email protected]

© 2006-2013 by Douglas Wilhelm Harder. Some rights reserved.


Stacks
2

3.2 Outline

This topic discusses the concept of a stack:


– Description of an Abstract Stack
– List applications
– Implementation
– Example applications
• Parsing: XHTML, C++
• Function calls
• Reverse-Polish calculators
• Robert’s Rules
– Standard Template Library
Stacks
3

3.2.1 Abstract Stack

An Abstract Stack (Stack ADT) is an abstract data type which


emphasizes specific operations:
– Uses a explicit linear ordering
– Insertions and removals are performed individually
– Inserted objects are pushed onto the stack
– The top of the stack is the most recently object pushed onto the stack
– When an object is popped from the stack, the current top is erased
Stacks
4

3.2.1 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
Stacks
5

3.2.2 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
Stacks
6

3.2.2 Stack: Applications

Problem solving:
– Solving one problem may lead to subsequent problems
– These problems may result in further problems
– As problems are solved, your focus shifts back to the problem which
lead to the solved problem

Notice that function calls behave similarly:


– A function is a collection of code which solves a problem

Reference: Donald Knuth


Stacks
7

3.2.3 Implementations

We will look at two implementations of stacks:

The optimal asymptotic run time of any algorithm is Q(1)


– The run time of the algorithm is independent of the number of objects
being stored in the container
– We will always attempt to achieve this lower bound

We will look at
– Singly linked lists
– One-ended arrays
Stacks
8

3.2.3.1 Linked-List Implementation

Operations at the front of a singly linked list are all Q(1)

Front/1st Back/nth
Find Q(1) Q(1)
Insert Q(1) Q(1)
Erase Q(1) Q(n)

The desired behaviour of an Abstract Stack may be reproduced by


performing all operations at the front
Stacks
9

3.2.3.1 Single_list Definition

The definition of single list class from Project 1 is:


template <typename Type>
class Single_list {
public:
Single_list();
~Single_list();

int size() const;


bool empty() const;
Type front() const;
Type back() const;
Single_node<Type> *head() const;
Single_node<Type> *tail() const;
int count( Type const & ) const;

void push_front( Type const & );


void push_back( Type const & );
Type pop_front();
int erase( Type const & );
};
Stacks
10

3.2.3.1 Stack-as-List Class

The stack class using a singly linked list has a single private
member variable:

template <typename Type>


class Stack {
private:
Single_list<Type> list;
public:
bool empty() const;
Type top() const;
void push( Type const & );
Type pop();
};
Stacks
11

3.2.3.1 Stack-as-List Class

A constructor and destructor is not needed


– Because list is declared, the compiler will call the constructor of the
Single_list class when the Stack is constructed

template <typename Type>


class Stack {
private:
Single_list<Type> list;
public:
bool empty() const;
Type top() const;
void push( Type const & );
Type pop();
};
Stacks
12

3.2.3.1 Stack-as-List Class

The empty and push functions just call the appropriate functions of
the Single_list class

template <typename Type>


bool Stack<Type>::empty() const {
return list.empty();
}

template <typename Type>


void Stack<Type>::push( Type const &obj ) {
list.push_front( obj );
}
Stacks
13

3.2.3.1 Stack-as-List Class

The top and pop functions, however, must check the boundary case:

template <typename Type>


Type Stack<Type>::top() const {
if ( empty() ) {
throw underflow();
}

template <typename Type>


return list.front();
Type Stack<Type>::pop() {
}
if ( empty() ) {
throw underflow();
}

return list.pop_front();
}
Stacks
14

3.2.3.2 Array Implementation

For one-ended arrays, all operations at the back are Q(1)

Front/1st Back/nth
Find Q(1) Q(1)
Insert Q(n) Q(1)
Erase Q(n) Q(1)
Stacks
15

3.2.3.2 Destructor

We need to store an array:


– In C++, this is done by storing the address of the first entry
Type *array;

We need additional information, including:


– The number of objects currently in the stack
int stack_size;
– The capacity of the array
int array_capacity;
Stacks
16

3.2.3.2 Stack-as-Array Class

We need to store an array:


– In C++, this is done by storing the address of the first entry
template <typename Type>
class Stack {
private:
int stack_size;
int array_capacity;
Type *array;
public:
Stack( int = 10 );
~Stack();
bool empty() const;
Type top() const;
void push( Type const & );
Type pop();
};
Stacks
17

3.2.3.2 Constructor

The class is only storing the address of the array


– We must allocate memory for the array and initialize the member
variables
– The call to new Type[array_capacity] makes a request to the
operating system for array_capacity objects

#include <algorithm>
// ...

template <typename Type>


Stack<Type>::Stack( int n ):
stack_size( 0 ),
array_capacity( std::max( 1, n ) ),
array( new Type[array_capacity] ) {
// Empty constructor
}
Stacks
18

3.2.3.2 Constructor

Warning: in C++, the variables are initialized in the order in which


they are defined:
template <typename Type>
class Stack {
template <typename Type> private:
Stack<Type>::Stack( int n ): int stack_size;
stack_size( 0 ), int array_capacity;
Type *array;
array_capacity( std::max( 1, n ) ),
public:
array( new Type[array_capacity] ) { Stack( int = 10 );
// Empty constructor ~Stack();
} bool empty() const;
Type top() const;
void push( Type const & );
Type pop();
};
Stacks
19

3.2.3.2 Destructor

The call to new in the constructor requested memory from the


operating system
– The destructor must return that memory to the operating system:

template <typename Type>


Stack<Type>::~Stack() {
delete [] array;
}
Stacks
20

3.2.3.2 Empty

The stack is empty if the stack size is zero:

template <typename Type>


bool Stack<Type>::empty() const {
return ( stack_size == 0 );
}

The following is unnecessarily tedious:


– The == operator evaluates to either true or false
if ( stack_size == 0 ) {
return true;
} else {
return false;
}
Stacks
21

3.2.3.2 Top

If there are n objects in the stack, the last is located at index n – 1

template <typename Type>


Type Stack<Type>::top() const {
if ( empty() ) {
throw underflow();
}

return array[stack_size - 1];


}
Stacks
22

3.2.3.2 Pop

Removing an object simply involves reducing the size


– It is invalid to assign the last entry to “0”
– By decreasing the size, the previous top of the stack is now at the
location stack_size

template <typename Type>


Type Stack<Type>::pop() {
if ( empty() ) {
throw underflow();
}

--stack_size;
return array[stack_size];
}
Stacks
23

3.2.3.2 Push

Pushing an object onto the stack can only be performed if the


array is not full

template <typename Type>


void Stack<Type>::push( Type const &obj ) {
if ( stack_size == array_capacity ) {
throw overflow(); // Best solution?????
}

array[stack_size] = obj;
++stack_size;
}
Stacks
24

3.2.3.2 Exceptions

The case where the array is full is not an exception defined in the
Abstract Stack

If the array is filled, we have five options:


– Increase the size of the array
– Throw an exception
– Ignore the element being pushed
– Replace the current top of the stack
– Put the pushing process to “sleep” until something else removes
the top of the stack

Include a member function bool full() const;


Stacks
25

3.2.4 Array Capacity

If dynamic memory is available, the best option is to increase the


array capacity

If we increase the array capacity, the question is:


– How much?
– By a constant? array_capacity += c;
– By a multiple? array_capacity *= c;
Stacks
26

3.2.4 Array Capacity

First, let us visualize what must occur to allocate new memory


Stacks
27

3.2.4 Array Capacity

First, this requires a call to new Type[N] 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
Stacks
28

3.2.4 Array Capacity

Next, the values must be copied over


Stacks
29

3.2.4 Array Capacity

The memory for the original array must be deallocated

W
Stacks
30

3.2.4 Array Capacity

Finally, the appropriate member variables must be reassigned


Stacks
31

3.2.4 Array Capacity

The implementation:
void double_capacity() {
Type *tmp_array = new Type[2*array_capacity];

}
Stacks
32

3.2.4 Array Capacity

The implementation:
void double_capacity() {
Type *tmp_array = new Type[2*array_capacity];

tmp_array

}
Stacks
33

3.2.4 Array Capacity

The implementation:
void double_capacity() {
Type *tmp_array = new Type[2*array_capacity];

for ( int i = 0; i < array_capacity; ++i ) {


tmp_array
tmp_array[i] = array[i];
}

}
Stacks
34

3.2.4 Array Capacity

The implementation:
void double_capacity() {
Type *tmp_array = new Type[2*array_capacity];

for ( int i = 0; i < array_capacity; ++i ) {


tmp_array
tmp_array[i] = array[i];
} W

delete [] array;

}
Stacks
35

3.2.4 Array Capacity

The implementation:
void double_capacity() {
Type *tmp_array = new Type[2*array_capacity];

for ( int i = 0; i < array_capacity; ++i ) {


tmp_array
tmp_array[i] = array[i];
}

delete [] array;
array = tmp_array;

array_capacity *= 2;
}
Stacks
36

3.2.4 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
Stacks
37

3.2.4 Array Capacity

To state the average run time, 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)
Stacks
38

3.2.4 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
Stacks
39

3.2.4 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
Stacks
40

3.2.4.1 Array Capacity

Suppose we insert n 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
n(n  1) n(n  1)
k 1

(k  1)   k   n 
 
 k 1  2
n 
2
  n2

– Therefore, the amortized number of copies


is given by
n
2 
   n 

 n 
– Therefore each push must run in
Q(n) time
– The wasted space, however
is Q(1)
Stacks
41

3.2.4.2 Array Capacity

Suppose we double the array size each time it is full:


– This is difficult to solve for an arbitrary n so instead, we will restrict
the number of objects we are inserting to n = 2h objects
– We will then assume that the behavior for intermediate values
of n will be similar
Stacks
42

3.2.4.2 Array Capacity

Suppose we double the array size each time it is full:


– Inserting n = 2h objects would therefore require
1, 2, 4, 8, …, 2h–1
copies, for once we add the last object, the array will be full
– The total number of copies is therefore:
h 1

 2 k  2
k 0
h 11
 1  2h  1  n  1    n 

– Therefore the amortized number of


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

3.2.4.3 Array Capacity

What if we increase the array size by a larger constant?


– For example, increase the array size by 4, 8, 100?
Stacks
44

3.2.4.3 Array Capacity

Suppose we increase it by a constant value m and we add n = ℓm


objects
– To add n items, we will have to make
m, 2m, 3m, …, (ℓ – 1)m
copies in total, or
1 1
   1  n
 km  m  k  m
2
   m2
     m    n 
 m
k 1 k 1

The amoritized number of copies is


n
     n
m
as m is fixed
Stacks
45

3.2.4.3 Array Capacity

Note the difference in worst-case amortized scenarios:


Copies per Unused
Insertion Memory
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

The web site


http://www.ece.uwaterloo.ca/~ece250/Algorithms/Array_resizing/
discusses the consequences of various values of r
Stacks
46

3.2.5 Application: Parsing

Most parsing uses stacks

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

3.2.5.1 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
Stacks
48

3.2.5.1 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
Stacks
49

3.2.5.1 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>
Stacks
50

3.2.5.1 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
Stacks
51

3.2.5.1 Parsing XHTML

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

<html>
Stacks
52

3.2.5.1 Parsing XHTML

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

<html> <head>
Stacks
53

3.2.5.1 Parsing XHTML

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

<html> <head> <title>


Stacks
54

3.2.5.1 Parsing XHTML

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

<html> <head> <title>


Stacks
55

3.2.5.1 Parsing XHTML

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

<html> <head>
Stacks
56

3.2.5.1 Parsing XHTML

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

<html> <body>
Stacks
57

3.2.5.1 Parsing XHTML

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

<html> <body> <p>


Stacks
58

3.2.5.1 Parsing XHTML

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

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


Stacks
59

3.2.5.1 Parsing XHTML

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

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


Stacks
60

3.2.5.1 Parsing XHTML

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

<html> <body> <p>


Stacks
61

3.2.5.1 Parsing XHTML

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

<html> <body>
Stacks
62

3.2.5.1 Parsing XHTML

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

<html>
Stacks
63

3.2.5.1 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
Stacks
64

3.2.5.1 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
Stacks
65

3.2.5.1 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
Stacks
66

3.2.5.2 Parsing C++

The next example shows how stacks may be used in parsing C++

Those taking ECE 351 Compilers will use this

For other students, it should help understand, in part:


– how a compiler works, and
– why programming languages have the structure they do
Stacks
67

3.2.5.2 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;
}
}

http://xkcd.com/859/
Stacks
68

3.2.5.2 Parsing C++

For C++, the errors are similar to that for XHTML, however:
– many XHTML parsers usually attempt to “correct” errors (e.g., insert
missing tags)
– C++ compilers will simply issue a parse error:
{eceunix:1} cat example1.cpp
#include <vector>
int main() {
std::vector<int> v(100];
return 0;
}

{eceunix:2} g++ example1.cpp


example1.cpp: In function 'int main()':
example1.cpp:3: error: expected ')' before ']' token
Stacks
69

3.2.5.2 Parsing C++

For C++, the errors are similar to that for XHTML, however:
– many XHTML parsers usually attempt to “correct” errors (e.g., insert
missing tags)
– C++ compilers will simply issue a parse error:
{eceunix:1} cat example2.cpp
#include <vector>
int main() {
std::vector<int> v(100);
v[0] = 3];
return 0;
}
{eceunix:2} g++ example2.cpp
example2.cpp: In function 'int main()':
example2.cpp:4: error: expected ';' before ']' token
Stacks
70

3.2.5.3 Function Calls

This next example discusses function calls

In ECE 222 Digital Computers, you will see how stacks are
implemented in hardware on all CPUs to facilitate function calling

The simple features of a stack indicate why almost all programming


languages are based on function calls
Stacks
71

3.2.5.3 Function Calls

Function calls are similar to problem solving presented earlier:


– you write a function to solve a problem
– the function may require sub-problems to be solved, hence, it may call
another function
– once a function is finished, it returns to the function which called it
Stacks
72

3.2.5.3 Function Calls

You will notice that the when a function returns, execution and the
return value is passed back to the last function which was called

This is again, the last-in—first-out property


– Covered in much greater detail in ECE 222

Today’s CPUs have hardware specifically designed to facilitate


function calling
Stacks
73

3.2.5.4 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
Stacks
74

3.2.5.4 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 –
7 5 × 6 –
35 6 –
29
Stacks
75

3.2.5.4 Reverse-Polish Notation

This is called reverse-Polish notation after the mathematician Jan


Łukasiewicz
– As you will see in ECE 222, this forms the basis
of the recursive stack used on all processors

He also made significant contributions to


logic and other fields
– Including humour…

http://www.audiovis.nac.gov.pl/
http://xkcd.com/645/
Stacks
76

3.2.5.4 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
Stacks
77

3.2.5.4 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
Stacks
78

3.2.5.4 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
Stacks
79

3.2.5.4 Reverse-Polish Notation

A quick example of postscript:

0 10 360 { % Go from 0 to 360 degrees in 10-degree steps


newpath % Start a new path
gsave % Keep rotations temporary
144 144 moveto
rotate % Rotate by degrees on stack from 'for'
72 0 rlineto
stroke
grestore % Get back the unrotated state
} for % Iterate over angles

http://www.tailrecursive.org/postscript/examples/rotate.html
Stacks
80

3.2.5.4 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
Stacks
81

3.2.5.4 Reverse-Polish Notation

Evaluate the following reverse-Polish expression using a stack:


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

3.2.5.4 Reverse-Polish Notation

Push 1 onto the stack


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

1
Stacks
83

3.2.5.4 Reverse-Polish Notation

Push 1 onto the stack


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

2
1
Stacks
84

3.2.5.4 Reverse-Polish Notation

Push 3 onto the stack


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

3
2
1
Stacks
85

3.2.5.4 Reverse-Polish Notation

Pop 3 and 2 and push 2 + 3 = 5


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

5
1
Stacks
86

3.2.5.4 Reverse-Polish Notation

Push 4 onto the stack


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

4
5
1
Stacks
87

3.2.5.4 Reverse-Polish Notation

Push 5 onto the stack


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

5
4
5
1
Stacks
88

3.2.5.4 Reverse-Polish Notation

Push 6 onto the stack


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

6
5
4
5
1
Stacks
89

3.2.5.4 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
Stacks
90

3.2.5.4 Reverse-Polish Notation

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


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

–26
5
1
Stacks
91

3.2.5.4 Reverse-Polish Notation

Push 7 onto the stack


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

7
–26
5
1
Stacks
92

3.2.5.4 Reverse-Polish Notation

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


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

–182
5
1
Stacks
93

3.2.5.4 Reverse-Polish Notation

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


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

–177
1
Stacks
94

3.2.5.4 Reverse-Polish Notation

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


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

178
Stacks
95

3.2.5.4 Reverse-Polish Notation

Push 8 onto the stack


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

8
178
Stacks
96

3.2.5.4 Reverse-Polish Notation

Push 1 onto the stack


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

9
8
178
Stacks
97

3.2.5.4 Reverse-Polish Notation

Pop 9 and 8 and push 8 × 9 = 72


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

72
178
Stacks
98

3.2.5.4 Reverse-Polish Notation

Pop 72 and 178 and push 178 + 72 = 250


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

250
Stacks
99

3.2.5.4 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
Stacks
100

3.2.5.4 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 × +
Stacks
101

3.2.5.5 Standard Template Library

The Standard Template Library (STL) has a wrapper class stack


with the following declaration:

template <typename T>


class stack {
public:
stack(); // not quite true...
bool empty() const;
int size() const;
const T & top() const;
void push( const T & );
void pop();
};
Stacks
102

3.2.6 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;
}
Stacks
103

3.2.6 Standard Template Library

The reason that the stack class is termed a wrapper is because it


uses a different container class to actually store the elements

The stack class simply presents the stack interface with


appropriately named member functions:
– push, pop , and top
Stacks
104

Stacks

The stack is the simplest of all ADTs


– Understanding how a stack works is trivial

The application of a stack, however, is not in the implementation,


but rather:
– Where possible, create a design which allows the use of a stack

We looked at:
– Parsing, function calls, and reverse Polish
Stacks
105

References

Donald E. Knuth, The Art of Computer Programming, Volume 1: Fundamental Algorithms, 3rd
Ed., Addison Wesley, 1997, §2.2.1, p.238.

Cormen, Leiserson, and Rivest, Introduction to Algorithms, McGraw Hill, 1990, §11.1, p.200.

Weiss, Data Structures and Algorithm Analysis in C++, 3rd Ed., Addison Wesley, §3.6, p.94.

Koffman and Wolfgang, “Objects, Abstraction, Data Strucutes and Design using C++”, John
Wiley & Sons, Inc., Ch. 5.

Wikipedia, http://en.wikipedia.org/wiki/Stack_(abstract_data_type)

These slides are provided for the ECE 250 Algorithms and Data Structures course. The
material in it reflects Douglas W. Harder’s best judgment in light of the information available to
him at the time of preparation. Any reliance on these course slides by any party for any other
purpose are the responsibility of such parties. Douglas W. Harder accepts no responsibility for
damages, if any, suffered by any party as a result of decisions made or actions based on these
course slides for any other purpose than that for which it was intended.

You might also like