Sie sind auf Seite 1von 5

Recall the Recursion Pattern (§ 2.

5)
Recursion: when a method calls itself
Classic example
- - the factorial function:
Using Recursion „ n! = 1· 2· 3· ··· · (n-1)· n
Recursive definition:

 1 if n = 0
f ( n) = 
n ⋅ f (n − 1) else
As a Java method:
// recursive factorial function
public static int recursiveFactorial(int n) {
if (n == 0) return 1; // basis case
else return n * recursiveFactorial(n- 1); // recursive case
}
© 2004 Goodrich, Tamassia Using Recursion 1 © 2004 Goodrich, Tamassia Using Recursion 2

A Simple Example of Linear


Linear Recursion (§ 4.1.1) Recursion
Test for base cases. Algorithm LinearSum(A, n): Example recursion trace:
„ Begin by testing for a set of base cases (there Input:
should be at least one). A integer array A and an integer call return 15 + A[4] = 15 + 5 = 20

„ Every possible chain of recursive calls must n = 1, such that A has at least LinearSum(A,5)

eventually reach a base case, and the handling of n elements call return 13 + A[3] = 13 + 2 = 15

each base case should not use recursion. Output: LinearSum (A,4)
The sum of the first n integers
Recur once. in A
call

LinearSum (A,3)
return 7 + A[2] = 7 + 6 = 13

„ Perform a single recursive call. (This recursive step if n = 1 then call return 4 + A[1] = 4 + 3 = 7
may involve a test that decides which of several return A[0] LinearSum (A,2)
possible recursive calls to make, but it should else call return A[0] = 4
ultimately choose to make just one of these calls return LinearSum(A, n - 1) + LinearSum (A,1)
each time we perform this step.) A[n - 1]
„ Define each possible recursive call so that it makes
progress towards a base case.
© 2004 Goodrich, Tamassia Using Recursion 3 © 2004 Goodrich, Tamassia Using Recursion 4
Reversing an Array Defining Arguments for Recursion
Algorithm ReverseArray(A, i, j): In creating recursive methods, it is important
Input: An array A and nonnegative integer to define the methods in ways that facilitate
indices i and j recursion.
Output: The reversal of the elements in A This sometimes requires we define additional
starting at index i and ending at j paramaters that are passed to the method.
if i < j then For example, we defined the array reversal
Swap A[i] and A[ j] method as ReverseArray(A, i, j), not
ReverseArray(A, i + 1, j - 1) ReverseArray(A).
return

© 2004 Goodrich, Tamassia Using Recursion 5 © 2004 Goodrich, Tamassia Using Recursion 6

Computing Powers Recursive Squaring


We can derive a more efficient linearly
The power function, p(x,n)=xn, can be recursive algorithm by using repeated squaring:
defined recursively:  1 if x = 0
 1 if n = 0 
p ( x, n ) =  p ( x, n) =  x ⋅ p ( x, (n − 1) / 2) 2 if x > 0 is odd
 x ⋅ p ( x, n − 1) else  p ( x , n / 2) 2 if x > 0 is even

This leads to an power function that runs in For example,
O(n) time (for we make n recursive calls). 24 = 2(4/2)2 = (24/2)2 = (22)2 = 42 = 16
25 = 21+(4/2)2 = 2(24/2)2 = 2(22)2 = 2(42) = 32
We can do better than this, however.
26 = 2(6/ 2)2 = (26/2)2 = (23)2 = 82 = 64
27 = 21+(6/2)2 = 2(26/2)2 = 2(23)2 = 2(82) = 128.

© 2004 Goodrich, Tamassia Using Recursion 7 © 2004 Goodrich, Tamassia Using Recursion 8
Analyzing the Recursive Squaring
A Recursive Squaring Method Method
Algorithm Power(x, n): Algorithm Power(x, n):
Input: A number x and integer n = 0 Input: A number x and
integer n = 0
Output: The value xn
Output: The value xn Each time we make a
if n = 0 then if n = 0 then recursive call we halve the
return 1 return 1 value of n; hence, we make
log n recursive calls. That
if n is odd then if n is odd then is, this method runs in
y = Power(x, (n - 1)/ 2) y = Power(x, (n - 1)/ 2) O(log n) time.
return x · y ·y return x · y · y
else It is important that we
else used a variable twice here
y = Power(x, n/ 2) y = Power(x, n/ 2) rather than calling the
return y · y return y · y method twice.

© 2004 Goodrich, Tamassia Using Recursion 9 © 2004 Goodrich, Tamassia Using Recursion 10

Tail Recursion Binary Recursion (§ 4.1.2)


Tail recursion occurs when a linearly recursive Binary recursion occurs whenever there are
method makes its recursive call as its last step.
The array reversal method is an example. two recursive calls for each non-base case.
Such methods can be easily converted to non - Example: the DrawTicks method for drawing
recursive methods (which saves on some resources).
ticks on an English ruler.
Example:
Algorithm IterativeReverseArray(A, i, j ):
Input: An array A and nonnegative integer indices i and j
Output: The reversal of the elements in A starting at
index i and ending at j
while i < j do
Swap A[i ] and A[ j ]
i =i+1
j =j-1
return
© 2004 Goodrich, Tamassia Using Recursion 11 © 2004 Goodrich, Tamassia Using Recursion 12
A Binary Recursive Method for
Drawing Ticks Another Binary Recusive Method
// draw a tick with no label
public static void drawOneTick(int tickLength) { drawOneTick(tickLength, - 1); } Problem: add all the numbers in an integer array A:
// draw one tick Algorithm BinarySum(A, i, n):
public static void drawOneTick(int tickLength, int tickLabel) {
for (int i = 0; i < tickLength; i++)
Input: An array A and integers i and n
System.out.print("-"); Output: The sum of the n integers in A starting at index i
if (tickLabel >= 0) System.out.print(" " + tickLabel); if n = 1 then
}
System.out.print("\n");
Note the two return A[i ]
public static void drawTicks(int tickLength) { // draw ticks of given length recursive calls return BinarySum(A, i, n/ 2) + BinarySum(A, i + n/ 2, n/ 2)
if (tickLength > 0) { // stop when length drops to 0
drawTicks(tickLength- 1); // recursively draw left ticks
drawOneTick(tickLength); // draw center tick Example trace:
drawTicks(tickLength- 1); // recursively draw right ticks
} 0, 8
}
public static void drawRuler(int nInches, int majorLength) { // draw ruler
drawOneTick(majorLength, 0); // draw tick 0 and its label 0, 4 4, 4
for (int i = 1; i <= nInches; i++) {
drawTicks(majorLength- 1); // draw ticks for this inch
drawOneTick(majorLength, i); // draw tick i and its label
0, 2 2, 2 4, 2 6, 2
}
}
0, 1 1, 1 2, 1 3, 1 4, 1 5, 1 6, 1 7, 1

© 2004 Goodrich, Tamassia Using Recursion 13 © 2004 Goodrich, Tamassia Using Recursion 14

Analyzing the Binary Recursion


Computing Fibanacci Numbers Fibonacci Algorithm
Let nk denote number of recursive calls made by
Fibonacci numbers are defined recursively: BinaryFib(k). Then
F0 = 0 „ n0 = 1
„ n1 = 1
F1 = 1
„ n2 = n1 + n0 + 1 = 1 + 1 + 1 = 3
Fi = Fi-1 + Fi-2 for i > 1. „ n3 = n2 + n1 + 1 = 3 + 1 + 1 = 5
As a recursive algorithm (first attempt): „ n4 = n3 + n2 + 1 = 5 + 3 + 1 = 9
Algorithm BinaryFib(k): „ n5 = n4 + n3 + 1 = 9 + 5 + 1 = 15
Input: Nonnegative integer k „ n6 = n5 + n4 + 1 = 15 + 9 + 1 = 25
Output: The kth Fibonacci number Fk „ n7 = n6 + n5 + 1 = 25 + 15 + 1 = 41
if k = 1 then „ n8 = n7 + n6 + 1 = 41 + 25 + 1 = 67.
return k Note that the value at least doubles for every other
else value of nk. That is, nk > 2k/2. It is exponential!
return BinaryFib(k - 1) + BinaryFib(k - 2)

© 2004 Goodrich, Tamassia Using Recursion 15 © 2004 Goodrich, Tamassia Using Recursion 16
A Better Fibonacci Algorithm Multiple Recursion (§ 4.1.3)
Use linear recursion instead:
Algorithm LinearFibonacci(k): Motivating example: summation puzzles
Input: A nonnegative integer k Š pot + pan = bib
Output: Pair of Fibonacci numbers (Fk, Fk-1) Š dog + cat = pig
if k = 1 then
return (k, 0) Š boy + girl = baby
else
(i, j) = LinearFibonacci(k - 1)
return (i +j, i) Multiple recursion: makes potentially
many recursive calls (not just one or
Runs in O(k) time. two).

© 2004 Goodrich, Tamassia Using Recursion 17 © 2004 Goodrich, Tamassia Using Recursion 18

Algorithm for Multiple Recursion Visualizing PuzzleSolve


Algorithm PuzzleSolve(k,S,U):
Input: An integer k, sequence S, and set U (the universe of elements to test)
Output: An enumeration of all k-length extensions to S using elements in U
without repetitions Initial call
for all e in U do PuzzleSolve(3,(),{a,b,c})
Remove e from U {e is now being used}
Add e to the end of S
if k = 1 then PuzzleSolve(2,b,{a,c}) PuzzleSolve(2,c,{a,b})
PuzzleSolve(2,a,{b,c})
Test whether S is a configuration that solves the puzzle
if S solves the puzzle then
return “Solution found: ” S PuzzleSolve(1,ab,{c}) PuzzleSolve(1,ba,{c}) PuzzleSolve(1,ca,{b})
else
abc bac cab
PuzzleSolve(k - 1, S,U) PuzzleSolve(1,ac,{b}) PuzzleSolve(1,bc,{a}) PuzzleSolve(1,cb,{a})
Add e back to U {e is now unused}
acb bca cba
Remove e from the end of S

© 2004 Goodrich, Tamassia Using Recursion 19 © 2004 Goodrich, Tamassia Using Recursion 20

Das könnte Ihnen auch gefallen