cs 15: data structures
TRANSCRIPT
CS 15: Data Structures
Project 1: CalcYouLater
• We’ll cover two subjects important to Project 1:‣ Reverse Polish Notation (RPN)
‣ Exceptions
• Also recommended:‣ Go back and review lecture on stacks
‣ Especially: parsing parenthesized expressions
Background
2
5 - 4 + 3 * 4 / 2 * 9
Conventional Arithmetic Notation
3
5 - 4 + 3 * 4 / 2 * 9
• There is some ambiguity here. We can resolve it with parentheses:
5 - (4 + 3) * (4 / (2 * 9))
Conventional Arithmetic Notation
3
5 - 4 + 3 * 4 / 2 * 9
• There is some ambiguity here. We can resolve it with parentheses:
5 - (4 + 3) * (4 / (2 * 9))
• There is still ambiguity here: Which comes first, - or *?
Conventional Arithmetic Notation
3
5 - 4 + 3 * 4 / 2 * 9
• There is some ambiguity here. We can resolve it with parentheses:
5 - (4 + 3) * (4 / (2 * 9))
• There is still ambiguity here: Which comes first, - or *?
• We have developed conventions to address this:1. Parentheses
2. Exponents
3. Multiplication/Division
4. Addition/Subtraction
Conventional Arithmetic Notation
3
PEMDAS
5 - 4 + 3 * 4 / 2 * 9
• There is some ambiguity here. We can resolve it with parentheses:
5 - (4 + 3) * (4 / (2 * 9))
• There is still ambiguity here: Which comes first, - or *?
• We have developed conventions to address this:1. Parentheses
2. Exponents
3. Multiplication/Division
4. Addition/Subtraction
Conventional Arithmetic Notation
3
PEMDAS
Notice: there is still ambiguity between mult/div and add/sub
5 - 4 + 3 * 4 / 2 * 9
• This is called infix notation: binary operators are placed between operands‣ Binary operator: operator that acts on two operands
Conventional Arithmetic Notation
4
5 - 4 + 3 * 4 / 2 * 9
• This is called infix notation: binary operators are placed between operands‣ Binary operator: operator that acts on two operands
• Infix notation is fundamentally ambiguous: we’ll always need parentheses, special rules like PEMDAS
Conventional Arithmetic Notation
4
• There is more than one way to write arithmetic expressions:
• infix: 3 + 4‣ Operator goes between operands
• prefix: + 3 4‣ Operator comes before operands
• postfix: 3 4 +‣ Operator comes after operands
Other Conventions
5
• There is more than one way to write arithmetic expressions:
• infix: 3 + 4‣ Operator goes between operands
• prefix: + 3 4‣ Operator comes before operands
• postfix: 3 4 +‣ Operator comes after operands
Other Conventions
5
Both prefix and postfix notation are ambiguity-free: no special rules needed, parentheses are optional
• There is more than one way to write arithmetic expressions:
• infix: 3 + 4‣ Operator goes between operands
• prefix: + 3 4‣ Operator comes before operands
• postfix: 3 4 +‣ Operator comes after operands
Other Conventions
6
• There is more than one way to write arithmetic expressions:
• infix: 3 + 4‣ Operator goes between operands
• prefix: + 3 4‣ Operator comes before operands
• postfix: 3 4 +‣ Operator comes after operands
Other Conventions
6
Invented by Polish logician Jan Łukasiewicz. Sometimes called Polish notation.
• There is more than one way to write arithmetic expressions:
• infix: 3 + 4‣ Operator goes between operands
• prefix: + 3 4‣ Operator comes before operands
• postfix: 3 4 +‣ Operator comes after operands
Other Conventions
7
• There is more than one way to write arithmetic expressions:
• infix: 3 + 4‣ Operator goes between operands
• prefix: + 3 4‣ Operator comes before operands
• postfix: 3 4 +‣ Operator comes after operands
Other Conventions
7
Invented by Polish logician Jan Łukasiewicz. Sometimes called Polish notation.
Sometimes called Reverse Polish notation (RPN)
What does this expression evaluate to:4 5 6 + *
RPN Example
8
What does this expression evaluate to:4 5 6 + *Evaluates to 44
RPN Example
8
What does this expression evaluate to:4 5 6 + *Evaluates to 44Read expression from left to right. Each time, we see an operator evaluate it on the previous two values:
RPN Example
8
What does this expression evaluate to:4 5 6 + *Evaluates to 44Read expression from left to right. Each time, we see an operator evaluate it on the previous two values:
1. + acts on previous two values, 5 and 6. This gives us 11.‣ Think of 11 as “replacing” 5 6 + in our expression
RPN Example
8
What does this expression evaluate to:4 5 6 + *Evaluates to 44Read expression from left to right. Each time, we see an operator evaluate it on the previous two values:
1. + acts on previous two values, 5 and 6. This gives us 11.‣ Think of 11 as “replacing” 5 6 + in our expression
2. * acts on previous two values, now 11 and 4. This gives us 44.
RPN Example
8
What does this expression evaluate to:5 2 * 3 + 7 +
RPN Example 2
9
What does this expression evaluate to:5 2 * 3 + 7 +Evaluates to 20
RPN Example 2
9
What does this expression evaluate to:5 2 * 3 + 7 +Evaluates to 20
RPN Example 2
9
What data structure can we use to evaluate RPN expressions?
• Answer: a stack!
• Stacks work well with RPN, since stacks let us access the most recently seen value(s)
RPN and Stacks
10
• Answer: a stack!
• Stacks work well with RPN, since stacks let us access the most recently seen value(s)
RPN and Stacks
10
Algorithm:
• Answer: a stack!
• Stacks work well with RPN, since stacks let us access the most recently seen value(s)
RPN and Stacks
10
Algorithm:Read in input one item at a time.
• Answer: a stack!
• Stacks work well with RPN, since stacks let us access the most recently seen value(s)
RPN and Stacks
10
Algorithm:Read in input one item at a time.Each time you see a number, push it on the stack.
• Answer: a stack!
• Stacks work well with RPN, since stacks let us access the most recently seen value(s)
RPN and Stacks
10
Algorithm:Read in input one item at a time.Each time you see a number, push it on the stack.Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
• Answer: a stack!
• Stacks work well with RPN, since stacks let us access the most recently seen value(s)
RPN and Stacks
10
Algorithm:Read in input one item at a time.Each time you see a number, push it on the stack.Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
RPN and Stacks
11
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
RPN and Stacks
12
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stackpush(6)
6
RPN and Stacks
13
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stackpush(5)
65
RPN and Stacks
14
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stackpush(2)
652
RPN and Stacks
15
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stackpush(3)
6523
RPN and Stacks
16
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
6523
RPN and Stacks
17
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stackop1 = pop() (= 3)
6523
RPN and Stacks
18
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stackop1 = pop() (= 3) op2 = pop() (=2)
6523
RPN and Stacks
19
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stackop1 = pop() (= 3) op2 = pop() (=2) res = 3 + 2 (= 5)
6523
RPN and Stacks
20
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stackop1 = pop() (= 3) op2 = pop() (=2) res = 3 + 2 (= 5) push(res)
655
RPN and Stacks
21
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
655
push(8)8
RPN and Stacks
22
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
655
pop() twice (get 8 and 5) 8
RPN and Stacks
23
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
655
pop() twice (get 8 and 5) res = 8 * 5 = 40 8
RPN and Stacks
24
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
65
pop() twice (get 8 and 5) res = 8 * 5 = 40 push(res) 40
RPN and Stacks
25
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
65
pop() twice (get 40 and 5)
40
RPN and Stacks
26
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
65
pop() twice (get 40 and 5) res = 40 + 5 = 45
40
RPN and Stacks
27
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
6
pop() twice (get 40 and 5) res = 40 + 5 = 45 push(45)
45
RPN and Stacks
28
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
6
push(3)
453
RPN and Stacks
29
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
6453
pop() twice (get 3 and 45)
RPN and Stacks
30
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
6453
pop() twice (get 3 and 45) res = 3 + 45 = 48
RPN and Stacks
31
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
6
pop() twice (get 3 and 45) res = 3 + 45 = 48 push(48)
48
RPN and Stacks
32
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
6
pop() twice (get 48 and 6)
48
RPN and Stacks
33
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
6
pop() twice (get 48 and 6) res = 48 * 6 = 288
48
RPN and Stacks
34
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stackpop() twice (get 48 and 6) res = 48 * 6 = 288 push(288)
288
RPN and Stacks
35
Algorithm: Read in input. Each time you see a number, push it on the stack. Each time you see a (binary) operator:
• Pop two numbers from the stack • Apply the operator to the two numbers • Push the result onto the stack.
When you have read the entire input, the value left on the stack is the result.
Evaluate:6 5 2 3 + 8 * + 3 + *
Stack
When done reading input, value left on stack is result. 288
• What do we do about operations like / and -, where order matters?
• For your project: Use the “deeper” item on the stack as the first operand
RPN and Stacks
36
• What do we do about operations like / and -, where order matters?
• For your project: Use the “deeper” item on the stack as the first operand
RPN and Stacks
37
Evaluate:6 2 /
Stack
• What do we do about operations like / and -, where order matters?
• For your project: Use the “deeper” item on the stack as the first operand
RPN and Stacks
38
Evaluate:6 2 /
Stackpush(6)
6
• What do we do about operations like / and -, where order matters?
• For your project: Use the “deeper” item on the stack as the first operand
RPN and Stacks
39
Evaluate:6 2 /
Stackpush(2)
62
• What do we do about operations like / and -, where order matters?
• For your project: Use the “deeper” item on the stack as the first operand
RPN and Stacks
40
Evaluate:6 2 /
Stack
62
• What do we do about operations like / and -, where order matters?
• For your project: Use the “deeper” item on the stack as the first operand
RPN and Stacks
41
Evaluate:6 2 /
Stackop2 = pop() (= 2)
62
• What do we do about operations like / and -, where order matters?
• For your project: Use the “deeper” item on the stack as the first operand
RPN and Stacks
42
Evaluate:6 2 /
Stackop2 = pop() (= 2) op1 = pop() (= 6)
62
• What do we do about operations like / and -, where order matters?
• For your project: Use the “deeper” item on the stack as the first operand
RPN and Stacks
43
Evaluate:6 2 /
Stackop2 = pop() (= 2) op1 = pop() (= 6) res = op1 / op2 = 3 6
2
Evaluate the following RPN expression. Use a stack to do so: write items in the stack for push() operations, and cross them out for pop() operations.3 4 2 / 5 * + 9 2 * 3 / -
RPN and Stacks Example
44
Evaluate the following RPN expression. Use a stack to do so: write items in the stack for push() operations, and cross them out for pop() operations.3 4 2 / 5 * + 9 2 * 3 / -
Answer: 7
RPN and Stacks Example
45
• The absence of ambiguity makes RPN very appealing for computers!
• A number of computers, calculators have historically used RPN‣ See, e.g., dc: A simple calculator program provided by Unix
RPN
46
3 + ((4 / 2) * 5) - ((9 * 2) / 3)3 4 2 / 5 * + 9 2 * 3 / - RPN: infix:
• The shunting algorithm developed by Edgar Dijkstra, converts expressions in infix notation to RPN
• It uses a stack and a queue
• Can you figure it out? Try it at home!
JFFE
47
• You will implemented an RPN calculator that performs basic arithmetic, and more:‣ Booleans and logical operations
‣ if statements
‣ Storing expressions to be executed later
‣ Reading from a file
‣ …and more!
Your Project
48
Exceptions
• When programming, an exception is like an error: it is an indicator that something has gone wrong
• In C++ (and other languages) we throw exceptions‣ Sometimes called “raising” an exception
• When an exception is thrown, either:‣ the program terminates, or
‣ we handle or catch the exception, and the program continues
Exceptions
50
• If we #include the C++ library stdexcept, we get access to many kinds of common exceptions:‣ runtime_error
‣ range_error
‣ system_error
‣ …
Kinds of Exceptions
51
• If we #include the C++ library stdexcept, we get access to many kinds of common exceptions:‣ runtime_error
‣ range_error
‣ system_error
‣ …
• Today we’ll use range_error as an example
• For your project you’ll use runtime_errors, but using them follows identical steps!
Kinds of Exceptions
51
• When we throw an exception, we typically provide an associated error message:
Throwing an Exception
52
int attempt_access(int arr[], int size, int index) { if (index < 0 or index >= size) throw range_error("Oh no! Given index was out of range.\n");
return arr[index]; }
• Once we throw an exception, if we do not have any special handling for it, the program will terminate
• In C++, we handle exceptions using try…catch… statements:
Handling Exceptions
53
try { …some code you want to run which may throw an exception… }catch(type_of_exc) { …code to execute in the case that a type_of_exc exception occurs…}
int second_attempt_access(int arr[], int size, int index) { try { int result = attempt_access(arr, size, index); cout << "Successfully accessed element!" << endl; return result; } catch (range_error) { cout << "Terrible! Got a range error! " << "Going to return 0 by default." << endl; return 0; } }
Handling Exceptions
54
int second_attempt_access(int arr[], int size, int index) { try { int result = attempt_access(arr, size, index); cout << "Successfully accessed element!" << endl; return result; } catch (range_error) { cout << "Terrible! Got a range error! " << "Going to return 0 by default." << endl; return 0; } }
• By catching a range_error exception, our program can continue running even though an exception was thrown
Handling Exceptions
54
• Sometimes we want to catch an exception, but still print the error message associated with it
• We can do this using a const reference along with the C++ what() method
Handling Exceptions
55
Catch and Print Exception
56
int third_attempt_access(int arr[], int size, int index) { try { int result = attempt_access(arr, size, index); cout << "Successfully accessed element!" << endl; return result; } catch (const range_error &e) { cout << "We just got the following error message:\n"; cout << e.what(); return 0; } }
• Let’s take a look at the full example: exceptions.cpp
Exceptions
57