Upload
jewel-howard
View
212
Download
0
Embed Size (px)
Citation preview
Recursion
Review:A recursive function calls itself, but with a smaller
problem – at least one of the parameters must
decrease.The function uses the results of the recursive call to
create its result.There must be a base case – when the problem is
sufficiently small to be solved directly, or by
another method.
Recursion - Example
Consider the following problem:
We want to print out the digits of a number (in
decimal) one by one. For example, the number
16425 would be printed out as:
1 6 4 2 5
How do we isolate a single digit of a number? Hint –
how do we get the one's place (5 in this example),
i.e., what arithmetic operation could we do to get 5
from 16425?
Example (cont'd)
Now that we can get the one's place (5), how do we
print out the rest of the number? What is the rest of
the number? Hint – pass the buck.
Exercise
How could we change the previous code to print out
the number in binary?
Recursion in General
We've seen examples where we code right a program
using either iteration or recursive – with the same
running times (finding the minimum element,
insertion sort, selection sort, mergesort, finding the
exponential), and two examples where it's easier to
write the program using recursion (quicksort and
the Tower of Hanoi).
Recursion (cont'd)
In theory, we can always use either to solve a
problem – but some problems are more naturally
solved using recursion, and some with iteration.
Bad Recursive Example
A classic problem:You have a pair of rabbits. Every
two years on the dot, a pair of rabbits produces a
new litter of exactly two rabbits. We assume that
our rabbits never die. How many pairs of rabbits
will we have in, say 6, years.
Year 1 2 3 4 5 6 7# Pairs 1 1 2 3 5 8 13
Fibonacci Sequence
This problem gives us the Fibonnaci sequence, f1 = 1,
f2 = 1, f
n = f
n-1 + f
n-2. Since the sequence is defined
recursively (the next value of f is defined in terms
of two previous values), it would seem natural to
write a recursive function to find the nth number in
the sequence.
Recursive Function
int fib(n) { if(n == 1 || n == 2) return 1; else return fib(n-1) + fib(n-2);}
What's wrong with this solution?
How the Computer Does Recursion
Basically, a recursive function is one that plays “Pass
the Buck” with itself as its own neighbor. For each
instance of the problem, the function keeps a record
of who called it (the calling function, and the point
in that function when it was called), and the
arguments – that is, the problem that it was given.
When it passes the buck to its neighbor (really
itself) it creates a new record with the new problem,
and places it on top of the old record.
How it Works (cont'd).
When it finishes a problem, it removes the top
record, and writes the answer in the record that is
now on top – the record with the previous problem
which has just been solved.
When it gets to the base case, it does not play Pass
the Buck, but rather just solves that problem
directly (runs the appropriate code) and returns the
answer to the calling function.
Example - Mergesort
Suppose that we use the mergesort function to sort
the list {4,2,1,7,6}, that is, a = {4,2,1,7,6}, low = 1,
and high = 5. A record is created with the calling
function (say main), the position in the calling
function, and the arguments. Since it's not the base
case, the mergesort function splits the list into two
pieces, and recurses, first posing the problem: a, 1,
3.
Example (cont'd)
A new record is created with the calling function
(mergesort), the position in that function (the first
recursive call to mergesort) and the new arguments:
a, 1, 3. That record is placed on top of the original
record (which does not reappear until the new
problem is solved). The mergesort function is called
again with the new arguments, a new record is
created (if not the base case) and so on...
Example (cont'd)
When the function finishes, it removes the top
record, and records the answer (the return value) in
the record that now is on top – the one with the
problem that the answer is the solution for.
Example (cont'd)
Calling function: main, line 3Arguments: a = {4, 2, 1, 7, 6}, 1, 6Result:
Calling function: mergesort, line 4Arguments: a = {4, 2, 1, 7, 6}, 1, 3Result:
Calling function: mergesort, line 4Arguments: a = {4, 2, 1, 7, 6}, 1, 2Result:
Calling Function: mergesort, line 4Arguments: a = {4, 2, 1, 7, 6}, 1, 1Result: {4}
Calling function: main, line 3Arguments: a = {4, 2, 1, 7, 6}, 1, 6Result:
Calling function: mergesort, line 4Arguments: a = {4, 2, 1, 7, 6}, 1, 3Result:
Calling function: mergesort, line 4Arguments: a = {4, 2, 1, 7, 6}, 1, 2Result:
Calling function: mergesort, line 5Arguments: a = {4, 2, 1, 7, 6}, 2, 2Result: {2}
Example (cont'd)
Calling function: main, line 3Arguments: a = {2, 4, 1, 7, 6}, 1, 6Result:
Calling function: mergesort, line 4Arguments: a = {2, 4, 1, 7, 6}, 1, 3Result:
Calling Function: mergesort, line 5Arguments: a = {2, 4, 1, 7, 6}, 3, 3Result: {1}
Example (cont'd)
Calling function: main, line 3Arguments: a = {1, 2, 4, 7, 6}, 1, 6Result:
Calling function: mergesort, line 4Arguments: a = {1, 2, 4, 7, 6}, 1, 3Result: {1, 2, 4}
Example (cont'd)
Calling function: main, line 3Arguments: a = {1, 2, 4, 7, 6}, 1, 6Result:
Calling function: mergesort, line 5Arguments: a = {1, 2, 4, 7, 6}, 4, 6Result: