Chapter 18 Recursion - PowerPoint PPT Presentation

Loading...

PPT – Chapter 18 Recursion PowerPoint presentation | free to download - id: 77de19-OWNjN



Loading


The Adobe Flash plugin is needed to view this content

Get the plugin now

View by Category
About This Presentation
Title:

Chapter 18 Recursion

Description:

Chapter 18 Recursion Chapter Goals To learn about the method of recursion To understand the relationship between recursion and iteration To analyze problems that are ... – PowerPoint PPT presentation

Number of Views:32
Avg rating:3.0/5.0
Slides: 102
Provided by: chand49
Learn more at: http://www.dsi.unive.it
Category:

less

Write a Comment
User Comments (0)
Transcript and Presenter's Notes

Title: Chapter 18 Recursion


1
Chapter 18 Recursion
2
Chapter Goals
  • To learn about the method of recursion
  • To understand the relationship between recursion
    and iteration
  • To analyze problems that are much easier to solve
    by recursion than by iteration
  • To learn to "think recursively"
  • To be able to use recursive helper methods
  • To understand when the use of recursion affects
    the efficiency of an algorithm

3
Triangle Numbers
  • Compute the area of a triangle of width n
  • Assume each square has an area of 1
  • Also called the nth triangle number
  • The third triangle number is 6

4
Outline of Triangle Class
public class Triangle public Triangle(int
aWidth) width aWidth public
int getArea() . . . private
int width
5
Handling Triangle of Width 1
  • The triangle consists of a single square
  • Its area is 1
  • Add the code to getArea method for width 1

public int getArea() if (width 1) return
1 . . .
6
Handling the General Case
  • Assume we know the area of the smaller, colored
    triangle
  • Area of larger triangle can be calculated as


smallerArea width
Continued
7
Handling the General Case
  • To get the area of the smaller triangle
  • Make a smaller triangle and ask it for its area

Triangle smallerTriangle new Triangle(width -
1) int smallerArea smallerTriangle.getArea()
8
Completed getArea method
public int getArea() if (width 1) return
1 Triangle smallerTriangle new
Triangle(width - 1) int smallerArea
smallerTriangle.getArea() return smallerArea
width
9
Computing the area of a triangle with width 4
  • getArea method makes a smaller triangle of width
    3
  • It calls getArea on that triangle
  • That method makes a smaller triangle of width 2
  • It calls getArea on that triangle
  • That method makes a smaller triangle of width 1
  • It calls getArea on that triangle
  • That method returns 1

Continued
10
Computing the area of a triangle with width 4
  • The method returns smallerArea width 1 2
    3
  • The method returns smallerArea width 3 3
    6
  • The method returns smallerArea width 6 4
    10

11
Recursion
  • A recursive computation solves a problem by using
    the solution of the same problem with simpler
    values
  • For recursion to terminate, there must be special
    cases for the simplest inputs.
  • To complete our Triangle example, we must handle
    width lt 0

if (width lt 0)  return 0
Continued
12
Recursion
  • Two key requirements for recursion success
  • Every recursive call must simplify the
    computation in some way
  • There must be special cases to handle the
    simplest computations directly

13
Other Ways to Compute Triangle Numbers
  • The area of a triangle equals the sum
  • Using a simple loop
  • Using math

1 2 3 . . . width
double area 0 for (int i 1 i lt width
i) area area i
1 2 . . . n n (n 1)/2 gt width
(width 1) / 2
14
File Triangle.java
01 / 02 A triangular shape composed of
stacked unit squares like this 03 04
05 06 . . . 07 / 08 public
class Triangle 09 10 / 11
Constructs a triangular shape. 12 _at_param
aWidth the width (and height) of the triangle 13
/ 14 public Triangle(int aWidth) 15
16 width aWidth 17
Continued
15
File Triangle.java
18 19 / 20 Computes the area of
the triangle. 21 _at_return the area 22
/ 23 public int getArea() 24 25
if (width lt 0) return 0 26 if (width
1) return 1 27 Triangle smallerTriangle
new Triangle(width - 1) 28 int
smallerArea smallerTriangle.getArea() 29
return smallerArea width 30 31 32
private int width 33
16
File TriangleTester.java
01 import java.util.Scanner 02 03 public
class TriangleTester 04 05 public static
void main(String args) 06 07
Scanner in new Scanner(System.in) 08
System.out.print("Enter width ") 09 int
width in.nextInt() 10 Triangle t new
Triangle(width) 11 int area
t.getArea() 12 System.out.println("Area
" area) 13 14
Continued
17
File triangle.java
Output
Enter width 10 Area 55
18
Self Check
  • Why is the statement in the getArea method
    unnecessary?
  • How would you modify the program to recursively
    compute the area of a square?

if (width 1) return 1
19
Answers
  1. Suppose we omit the statement. When computing the
    area of a triangle with width 1, we compute the
    area of the triangle with width 0 as 0, and then
    add 1, to arrive at the correct area.

Continued
20
Answers
  1. You would compute the smaller area recursively,
    then return
    Of course, it would be simpler
    to compute

smallerArea width width - 1.
21
Permutations
  • Design a class that will list all permutations of
    a string
  • A permutation is a rearrangement of the letters
  • The string "eat" has six permutations "eat"
    "eta" "aet" "tea" "tae"

22
Public Interface of PermutationGenerator
public class PermutationGenerator public
PermutationGenerator(String aWord) . . .
ArrayListltStringgt getPermutations() . . .
23
File PermutationGeneratorTester.java
01 import java.util.ArrayList 02 03 /
04 This program tests the permutation
generator. 05 / 06 public class
PermutationGeneratorTester 07 08 public
static void main(String args) 09 10
PermutationGenerator generator 11
new PermutationGenerator("eat") 12
ArrayListltStringgt permutations
generator.getPermutations() 13 for
(String s permutations) 14 15
System.out.println(s) 16
Continued
24
File PermutationGeneratorTester.java
17 18 19
25
File PermutationGeneratorTester.java
Output
eat eta aet ate tea tae
26
To Generate All Permutations
  • Generate all permutations that start with 'e' ,
    then 'a' then 't'
  • To generate permutations starting with 'e', we
    need to find all permutations of "at"
  • This is the same problem with simpler inputs.
  • Use recursion

27
To Generate All Permutations
  • getPermutations loop through all positions in
    the word to be permuted
  • For each position, compute the shorter word
    obtained by removing ith letter

String shorterWord word.substring(0, i)
word.substring(i 1)
Continued
28
To Generate All Permutations
  • Construct a permutation generator to get
    permutations of the shorter word

PermutationGenerator shorterPermutationGenerator
new PermutationGenerator(shorterWord) Arra
yListltStringgt shorterWordPermutations
shorterPermutationGenerator.getPermutations()
29
To Generate All Permutations
  • Finally, add the removed letter to front of all
    permutations of the shorter word
  • Special case simplest possible string is the
    empty string single permutation, itself

for (String s shorterWordPermutations)
result.add(word.charAt(i) s)
30
File PermutationGenerator.java
01 import java.util.ArrayList 02 03 / 04
This class generates permutations of a
word. 05 / 06 public class PermutationGenerator
07 08 / 09 Constructs a
permutation generator. 10 _at_param aWord the
word to permute 11 / 12 public
PermutationGenerator(String aWord) 13 14
word aWord 15 16
Continued
31
File PermutationGenerator.java
17 / 18 Gets all permutations of a
given word. 19 / 20 public
ArrayListltStringgt getPermutations() 21 22
ArrayListltStringgt result new
ArrayListltStringgt() 23 24 // The empty
string has a single permutation itself 25
if (word.length() 0) 26 27
result.add(word) 28 return result
29 30 31 // Loop through all
character positions 32 for (int i 0 i lt
word.length() i) 33
Continued
32
File PermutationGenerator.java
34 // Form a simpler word by removing
the ith character 35 String shorterWord
word.substring(0, i) 36
word.substring(i 1) 37 38 //
Generate all permutations of the simpler word 39
PermutationGenerator shorterPermutationGe
nerator 40 new
PermutationGenerator(shorterWord) 41
ArrayListltStringgt shorterWordPermutations 42
shorterPermutationGenerator.getPermu
tations() 43 44 // Add the removed
character to the front of 45 // each
permutation of the simpler word, 46
for (String s shorterWordPermutations) 47
48 result.add(word.charAt(i)
s) 49 50
Continued
33
File PermutationGenerator.java
51 // Return all permutations 52
return result 53 54 55 private
String word 56
34
Self Check
  1. What are all permutations of the four-letter word
    beat?
  2. Our recursion for the permutation generator stops
    at the empty string. What simple modification
    would make the recursion stop at strings of
    length 0 or 1?

35
Answers
  1. They are b followed by the six permutations of
    eat, e followed by the six permutations of bat, a
    followed by the six permutations of bet, and t
    followed by the six permutations of bea.
  2. Simply change because a word with a single
    letter is also its sole permutation.

if (word.length() 0) to if (word.length() lt 1)
36
Tracing Through Recursive Methods
Figure 1 Debugging a Recursive Method
37
Thinking Recursively
  • Problem test whether a sentence is a palindrome
  • Palindrome a string that is equal to itself when
    you reverse all characters
  • A man, a plan, a canalPanama!
  • Go hang a salami, I'm a lasagna hog
  • Madam, I'm Adam

38
Implement isPalindrome Method
public class Sentence / Constructs a
sentence. _at_param aText a string containing
all characters of the sentence /
public Sentence(String aText) text
aText
Continued
39
Implement isPalindrome Method
/ Tests whether this sentence is a
palindrome. _at_return true if this sentence
is a palindrome, false otherwise /
public boolean isPalindrome() . .
. private String text
40
Thinking Recursively Step-by-Step
  • Consider various ways to simplify inputs Here
    are several possibilities
  • Remove the first character
  • Remove the last character
  • Remove both the first and last characters
  • Remove a character from the middle

41
Thinking Recursively Step-by-Step
  • Combine solutions with simpler inputs into a
    solution of the original problem
  • Most promising simplification remove first and
    last characters "adam, I'm Ada", is a palindrome
    too!
  • Thus, a word is a palindrome if
  • The first and last letters match, and
  • Word obtained by removing the first and last
    letters is a palindrome

Continued
42
Thinking Recursively Step-by-Step
  • Combine solutions with simpler inputs into a
    solution of the original problem
  • What if first or last character is not a letter?
    Ignore it
  • If the first and last characters are letters,
    check whether they match if so, remove both and
    test shorter string
  • If last character isn't a letter, remove it and
    test shorter string
  • If first character isn't a letter, remove it and
    test shorter string

43
Thinking Recursively Step-by-Step
  • Find solutions to the simplest inputs
  • Strings with two characters
  • No special case required step two still applies
  • Strings with a single character
  • They are palindromes
  • The empty string
  • It is a palindrome

44
Thinking Recursively Step-by-Step
  1. Implement the solution by combining the simple
    cases and the reduction step

public boolean isPalindrome() int length
text.length() // Separate case for
shortest strings. if (length lt 1) return
true // Get first and last characters,
converted to lowercase. char first
Character.toLowerCase(text.charAt(0)) char
last Character.toLowerCase(text.charAt(length -
1))
Continued
45
Thinking Recursively Step-by-Step
if (Character.isLetter(first)
Character.isLetter(last)) // Both are
letters. if (first last)
// Remove both first and last character.
Sentence shorter new
Sentence(text.substring(1, length - 1))
return shorter.isPalindrome() else
return false
Continued
46
Thinking Recursively Step-by-Step
else if (!Character.isLetter(last))
// Remove last character. Sentence shorter
new Sentence(text.substring(0,
length - 1)) return shorter.isPalindrome()
else // Remove first
character. Sentence shorter new
Sentence(text.substring(1)) return
shorter.isPalindrome()
47
Recursive Helper Methods
  • Sometimes it is easier to find a recursive
    solution if you make a slight change to the
    original problem
  • Consider the palindrome test of previous slide
    It is a bit inefficient to construct new
    Sentence objects in every step

Continued
48
Recursive Helper Methods
  • Rather than testing whether the sentence is a
    palindrome, check whether a substring is a
    palindrome

/ Tests whether a substring of the sentence
is a palindrome. _at_param start the index of the
first character of the substring _at_param
end the index of the last character of the
substring _at_return true if the substring is a
palindrome / public boolean isPalindrome(int
start, int end)
49
Recursive Helper Methods
  • Then, simply call the helper method with
    positions that test the entire string

public boolean isPalindrome() return
isPalindrome(0, text.length() - 1)
50
Recursive Helper Methods isPalindrome
public boolean isPalindrome(int start, int
end) // Separate case for substrings of
length 0 and 1. if (start gt end) return
true // Get first and last characters,
converted to lowercase. char first
Character.toLowerCase(text.charAt(start))
char last Character.toLowerCase(text.charAt(end)
)
Continued
51
Recursive Helper Methods isPalindrome
if (Character.isLetter(first)
Character.isLetter(last)) if (first
last) // Test substring that
doesnt contain the matching
letters. return isPalindrome(start 1,
end - 1) else
return false else if (!Character.isLetter
(last)) // Test substring that doesnt
contain the last character. return
isPalindrome(start, end - 1)
Continued
52
Recursive Helper Methods isPalindrome
else // Test substring that doesnt
contain the first character. return
isPalindrome(start 1, end)
53
Self Check
  1. Do we have to give the same name to both
    isPalindrome methods?
  2. When does the recursive isPalindrome method stop
    calling itself?

54
Answers
  1. Nothe first one could be given a different name
    such as substringIsPalindrome.
  2. When start gt end, that is, when the investigated
    string is either empty or has length 1.

55
Fibonacci Sequence
  • Fibonacci sequence is a sequence of numbers
    defined by
  • First ten terms

1, 1, 2, 3, 5, 8, 13, 21, 34, 55
56
File FibTester.java
01 import java.util.Scanner 02 03 / 04
This program computes Fibonacci numbers using a
recursive 05 method. 06 / 07 public class
FibTester 08 09 public static void
main(String args) 10 11 Scanner
in new Scanner(System.in) 12
System.out.print("Enter n ") 13 int n
in.nextInt() 14 15 for (int i 1 i lt
n i) 16
Continued
57
File FibTester.java
17 long f fib(i) 18
System.out.println("fib(" i ") " f) 19
20 21 22 / 23
Computes a Fibonacci number. 24 _at_param n
an integer 25 _at_return the nth Fibonacci
number 26 / 27 public static long
fib(int n) 28 29 if (n lt 2)
return 1 30 else return fib(n - 1)
fib(n - 2) 31 32
Continued
58
File PermutationGeneratorTester.java
Output
Enter n 50 fib(1) 1 fib(2) 1 fib(3) 2
fib(4) 3 fib(5) 5 fib(6) 8 fib(7) 13
. . . fib(50) 12586269025
59
The Efficiency of Recursion
  • Recursive implementation of fib is
    straightforward
  • Watch the output closely as you run the test
    program
  • First few calls to fib are quite fast
  • For larger values, the program pauses an
    amazingly long time between outputs
  • To find out the problem, lets insert trace
    messages

60
File FibTrace.java
01 import java.util.Scanner 02 03 / 04
This program prints trace messages that show how
often the 05 recursive method for computing
Fibonacci numbers calls itself. 06 / 07
public class FibTrace 08 09 public static
void main(String args) 10 11
Scanner in new Scanner(System.in) 12
System.out.print("Enter n ") 13 int n
in.nextInt() 14 15 long f fib(n) 16
17 System.out.println("fib(" n ") "
f) 18
Continued
61
File FibTrace.java
19 20 / 21 Computes a Fibonacci
number. 22 _at_param n an integer 23
_at_return the nth Fibonacci number 24 / 25
public static long fib(int n) 26 27
System.out.println("Entering fib n " n) 28
long f 29 if (n lt 2) f 1 30
else f fib(n - 1) fib(n - 2) 31
System.out.println("Exiting fib n " n 32
" return value " f) 33
return f 34 35
62
File FibTrace.java
Output
Enter n 6 Entering fib n 6 Entering fib n
5 Entering fib n 4 Entering fib n
3 Entering fib n 2 Exiting fib n 2 return
value 1 Entering fib n 1 Exiting fib n 1
return value 1 Exiting fib n 3 return value
2 Entering fib n 2 Exiting fib n 2 return
value 1 Exiting fib n 4 return value 3
Continued
63
File FibTrace.java
Entering fib n 3 Entering fib n 2 Exiting
fib n 2 return value 1 Entering fib n
1 Exiting fib n 1 return value 1 Exiting
fib n 3 return value 2 Exiting fib n 5
return value 5 Entering fib n 4 Entering
fib n 3 Entering fib n 2 Exiting fib n 2
return value 1 Entering fib n 1 Exiting fib
n 1 return value 1 Exiting fib n 3 return
value 2 Entering fib n 2 Exiting fib n 2
return value 1 Exiting fib n 4 return value
3 Exiting fib n 6 return value 8 fib(6)
8
64
Call Tree for Computing fib(6)
Figure 2 Call Tree of the Recursive fib method
65
The Efficiency of Recursion
  • Method takes so long because it computes the same
    values over and over
  • The computation of fib(6) calls fib(3) three
    times
  • Imitate the pencil-and-paper process to avoid
    computing the values more than once

66
File FibLoop.java
01 import java.util.Scanner 02 03 / 04
This program computes Fibonacci numbers using an
// iterative method. 05 / 06
public class FibLoop 07 08 public static
void main(String args) 09 10
Scanner in new Scanner(System.in) 11
System.out.print("Enter n ") 12 int n
in.nextInt() 13 14 for (int i 1 i lt
n i) 15
Continued
67
File FibLoop.java
16 long f fib(i) 17
System.out.println("fib(" i ") " f) 18
19 20 21 / 22
Computes a Fibonacci number. 23 _at_param n
an integer 24 _at_return the nth Fibonacci
number 25 / 26 public static long
fib(int n) 27 28 if (n lt 2)
return 1 29 long fold 1 30 long
fold2 1 31 long fnew 1 32 for
(int i 3 i lt n i) 33
Continued
68
File FibLoop.java
34 fnew fold fold2 35
fold2 fold 36 fold fnew 37
38 return fnew 39 40
69
File PermutationGeneratorTester.java
Output
Enter n 50 fib(1) 1 fib(2) 1 fib(3) 2
fib(4) 3 fib(5) 5 fib(6) 8 fib(7) 13
. . . fib(50) 12586269025
70
The Efficiency of Recursion
  • Occasionally, a recursive solution runs much
    slower than its iterative counterpart
  • In most cases, the recursive solution is only
    slightly slower
  • The iterative isPalindrome performs only slightly
    better than recursive solution
  • Each recursive method call takes a certain amount
    of processor time

71
The Efficiency of Recursion
  • Smart compilers can avoid recursive method calls
    if they follow simple patterns
  • Most compilers don't do that
  • In many cases, a recursive solution is easier to
    understand and implement correctly than an
    iterative solution
  • "To iterate is human, to recurse divine.", L.
    Peter Deutsch

72
Iterative isPalindrome Method
public boolean isPalindrome() int start
0 int end text.length() - 1 while (start lt
end) char first Character.toLowerCase
(text.charAt(start)) char last
Character.toLowerCase(text.charAt(end) if
(Character.isLetter(first) Character.isLetter(l
ast)) // Both are letters.
if (first last)
start end--
Continued
73
Iterative isPalindrome Method
else return false
if (!Character.isLetter(last))
end-- if (!Character.isLetter(first))
start return true
74
Self Check
  1. You can compute the factorial function either
    with a loop, using the definition that n! 1 2
    . . . n, or recursively, using the definition
    that 0! 1 and n! (n - 1)! n. Is the
    recursive approach inefficient in this case?
  2. Why isn't it easy to develop an iterative
    solution for the permutation generator?

75
Answers
  1. No, the recursive solution is about as efficient
    as the iterative approach. Both require n - 1
    multiplications to compute n!.

Continued
76
Answers
  1. An iterative solution would have a loop whose
    body computes the next permutation from the
    previous ones. But there is no obvious mechanism
    for getting the next permutation. For example, if
    you already found permutations eat, eta, and aet,
    it is not clear how you use that information to
    get the next permutation. Actually, there is an
    ingenious mechanism for doing just that, but it
    is far from obvioussee Exercise P18.12.

77
The Limits of Computation
Figure 3 Alan Turing
78
The Limits of Computation
Figure 4 A Turing Machine
79
Using Mutual Recursions
  • Problem to compute the value of arithmetic
    expressions such as
  • Computing expression is complicated
  • and / bind more strongly than and -
  • parentheses can be used to group subexpressions

3 4 5 (3 4) 5 1 - (2 - (3 - (4 - 5)))
80
Syntax Diagram for Evaluating an Expression
Figure 5 Syntax Diagrams for Evaluating an
Expression
81
Using Mutual Recursions
  • An expression can broken down into a sequence of
    terms, separated by or -
  • Each term is broken down into a sequence of
    factors, separated by or /
  • Each factor is either a parenthesized expression
    or a number
  • The syntax trees represent which operations
    should be carried out first

82
Syntax Tree for Two Expressions
Figure 6 Syntax Trees for Two Expressions
83
Mutually Recursive Methods
  • In a mutual recursion, a set of cooperating
    methods calls each other repeatedly
  • To compute the value of an expression, implement
    3 methods that call each other recursively
  • getExpressionValue
  • getTermValue
  • getFactorValue

84
The getExpressionValue Method
public int getExpressionValue() int value
getTermValue() boolean done false while
(!done) String next
tokenizer.peekToken() if ("".equals(next)
"-".equals(next))
tokenizer.nextToken() // Discard "" or "-"
int value2 getTermValue() if
("".equals(next)) value value value2
else value value - value2 else
done true return value
85
The getFactorValue Method
public int getFactorValue() int value
String next tokenizer.peekToken() if
("(".equals(next)) tokenizer.nextToken(
) // Discard "(" value
getExpressionValue() tokenizer.nextToken()
// Discard ")" else value
Integer.parseInt(tokenizer.nextToken())
return value
86
Using Mutual Recursions
  • To see the mutual recursion clearly, trace
    through the expression (34)5
  • getExpressionValue calls getTermValue
  • getTermValue calls getFactorValue
  • getFactorValue consumes the ( input
  • getFactorValue calls getExpressionValue
  • getExpressionValue returns eventually with the
    value of 7, having consumed 3 4. This is the
    recursive call.
  • getFactorValue consumes the ) input
  • getFactorValue returns 7

Continued
87
Using Mutual Recursions
  • getTermValue consumes the inputs and 5 and
    returns 35
  • getExpressionValue returns 35

88
File Evaluator.java
01 / 02 A class that can compute the value
of an arithmetic expression. 03
/ 04 public class Evaluator 05 06
/ 07 Constructs an evaluator. 08
_at_param anExpression a string containing the
expression 09 to be evaluated 10
/ 11 public Evaluator(String
anExpression) 12 13 tokenizer new
ExpressionTokenizer(anExpression) 14 15
Continued
89
File Evaluator.java
16 / 17 Evaluates the
expression. 18 _at_return the value of the
expression. 19 / 20 public int
getExpressionValue() 21 22 int value
getTermValue() 23 boolean done
false 24 while (!done) 25 26
String next tokenizer.peekToken() 27
if ("".equals(next) "-".equals(next)) 28
29 tokenizer.nextToken()
// Discard "" or "-" 30 int
value2 getTermValue() 31 if
("".equals(next)) value value value2 32
else value value - value2 33

Continued
90
File Evaluator.java
34 else done true 35 36
return value 37 38 39 / 40
Evaluates the next term found in the
expression. 41 _at_return the value of the
term 42 / 43 public int
getTermValue() 44 45 int value
getFactorValue() 46 boolean done
false 47 while (!done) 48 49
String next tokenizer.peekToken() 50
if ("".equals(next) "/".equals(next)) 51

Continued
91
File Evaluator.java
52 tokenizer.nextToken() 53
int value2 getFactorValue() 54
if ("".equals(next)) value value
value2 55 else value value /
value2 56 57 else done
true 58 59 return value 60
61 62 / 63 Evaluates the next
factor found in the expression. 64 _at_return
the value of the factor 65 /
Continued
92
File Evaluator.java
66 public int getFactorValue() 67 68
int value 69 String next
tokenizer.peekToken() 70 if
("(".equals(next)) 71 72
tokenizer.nextToken() // Discard "(" 73
value getExpressionValue() 74
tokenizer.nextToken() // Discard ")" 75
76 else 77 value
Integer.parseInt(tokenizer.nextToken()) 78
return value 79 80 81 private
ExpressionTokenizer tokenizer 82
93
File ExpressionTokenizer.java
01 / 02 This class breaks up a string
describing an expression 03 into tokens
numbers, parentheses, and operators. 04 / 05
public class ExpressionTokenizer 06 07
/ 08 Constructs a tokenizer. 09
_at_param anInput the string to tokenize 10
/ 11 public ExpressionTokenizer(String
anInput) 12 13 input anInput 14
start 0 15 end 0 16
nextToken() 17
Continued
94
File ExpressionTokenizer.java
18 19 / 20 Peeks at the next token
without consuming it. 21 _at_return the next
token or null if there are no //
more tokens 22 / 23 public String
peekToken() 24 25 if (start gt
input.length()) return null 26 else
return input.substring(start, end) 27
28 29 / 30 Gets the next token
and moves the tokenizer to // the
following token. 31 _at_return the next token
or null if there are no // more
tokens 32 /
Continued
95
File ExpressionTokenizer.java
33 public String nextToken() 34 35
String r peekToken() 36 start
end 37 if (start gt input.length())
return r 38 if (Character.isDigit(input.ch
arAt(start))) 39 40 end
start 1 41 while (end lt
input.length() 42
Character.isDigit(input.charAt(end))) 43
end 44 45 else 46
end start 1 47 return r 48

Continued
96
File ExpressionTokenizer.java
50 private String input 51 private int
start 52 private int end 53
97
File EvaluatorTester.java
01 import java.util.Scanner 02 03 / 04
This program tests the expression evaluator.
05 / 06 public class EvaluatorTester 07
08 public static void main(String args)
09 10 Scanner in new
Scanner(System.in) 11 System.out.print("E
nter an expression ") 12 String input
in.nextLine() 13 Evaluator e new
Evaluator(input) 14 int value
e.getExpressionValue() 15
System.out.println(input "" value) 16
17
Continued
98
File EvaluatorTester.java
  • Output

Enter an expression 345 34523
99
Self Check
  1. What is the difference between a term and a
    factor? Why do we need both concepts?
  2. Why does the expression parser use mutual
    recursion?
  3. What happens if you try to parse the illegal
    expression 34)5? Specifically, which method
    throws an exception?

100
Answers
  1. Factors are combined by multiplicative operators
    ( and /), terms are combined by additive
    operators (, -). We need both so that
    multiplication can bind more strongly than
    addition.
  2. To handle parenthesized expressions, such as
    23(45). The subexpression 45 is handled by a
    recursive call to getExpressionValue.

Continued
101
Answers
  1. The Integer.parseInt call in getFactorValue
    throws an exception when it is given the string
    ")".
About PowerShow.com