Upload
clarence-mcgee
View
215
Download
3
Embed Size (px)
Citation preview
AK IT: Softwarekonstruktion 1
Session 05:C# Recursion
FactorialRecursion stackBinary Search
Towers of Hanoi
FEN 2013-03-02
FEN 2013-03-02 AK IT: Softwarekonstruktion 2
Recursion• In programming languages recursion is when a method is
calling it self (recursion may be indirectly)• Recursion often comes around when a problem can be
solved using a divide and conquer strategy:– If the problem is small, we can apply some simple (non-recursive)
solution. (called “base case”) – Otherwise the problem is divided into smaller sub problems of the
same kind. The sub problems are then solved by applying the solution recursively to the sub problems.
– Eventually the sub problems become so small that the simple solution can be applied, and recursion terminates.
– When the sub problems are solved, the solutions to the sub problems are combined into a solution to the original problem.
Recursion –Divide and Conquer
FEN 2013-03-02 AK IT: Softwarekonstruktion 3
• Divide:– If the problem is small, we can apply
some simple (non-recursive) solution (called “base case”).
– Otherwise the problem is divided into smaller sub problems of the same kind. The sub problems are then solved by applying the solution recursively to the sub problems.
– Eventually the sub problems become so small that the simple solution can be applied, and recursion terminates.
– Note the similarities to loops
• Conquer:– Simple sub problems are
solved using the non-recursive solution
– When the sub problems are solved, the solutions to the sub problems are combined into a solution to the original problem.
FEN 2013-03-02 AK IT: Softwarekonstruktion 4
Example• Many mathematical functions may be defined recursively. For
instance, computing the factorial of an number n (n!):
n! = n * (n-1)! for n > 0 n! = 1 for n = 0
• The base case (simple problem) is when n=0• If n>0 the problem is divided into the subproblem of
computing the factorial of n-1• The combine part is multiplying the result of (n-1)! by n.
Note: There must be a base case, so
recursion eventually stops.
FEN 2013-03-02 AK IT: Softwarekonstruktion 5
Recursive Factorial in C#
public static long Fac(long n) { calls++; if (n == 0) return 1; else return n * Fac(n - 1); }
FEN 2013-03-02 AK IT: Softwarekonstruktion 6
Behind the Scenes:The Recursion Stack
• When a recursive method executes many activations of the method exist at the same time.
• The virtual machine is handling this by storing the different states of the method on a stack:– Value of parameters and local variables– Return address
• When a method is called, an activation is created and pushed onto the stack
• When a method returns, its activation is popped from the stack
• The current activation of the method is always the topmost on the stack, and it is the values of parameters, local variables etc. stored that is used.
• A stack is a list, where insert (push) and remove (pop) are done at the front of the list (stack top).
Stack:
top
FEN 2013-03-02 AK IT: Softwarekonstruktion 7
Iterative Factorial• Actual it is not very smart to compute the factorial of n
recursively – a loop can do the job much more efficiently:
public long FacIter(int n){
long fac = 1; for (int i = 2; i <= n; i++) fac = fac * i; return fac; }
But is it more
simple?
public long Fac(int n)
if (n == 0 || n == 1) return 1; else return n * Fac(n-1);}
Exercise
• Write a recursive method that computes the sum of the first n non-negative numbers.
• Hint: the sum may be define by:•
sum(n) = n + sum(n-1) for n > 0sum(n) = 0 for n = 0
• Draw pictures of the recursion stack when sum(3) is computed
FEN 2013-03-02 AK IT: Softwarekonstruktion 8
FEN 2013-03-02 AK IT: Softwarekonstruktion 9
Binary Search• In a sorted random access (array based) data set it is possible to use
binary search.• Binary search can be formulated very simply using recursion:• Strategy:
If - the search set is emptyThen - the searched element, s, is not in the setElse - inspect the middle element, m
- If - m == s- Then - the element is found and we are done- Else - If - m > s
- Then - search in the lower half of the set - Else - search in the upper half of the set
Note the recursive nature of this solution!
FEN 2013-03-02 AK IT: Softwarekonstruktion 10
In C#…public static bool BinSearch(int l, int h, int x, int[] T){ //PRE T is sorted //Looking for x between l and h in T calls++; int m; if (l > h) return false; else { m = (l + h) / 2; if (x == T[m]) return true; else if (x > T[m]) return BinSearch(m + 1, h, x, T); else return BinSearch(l, m - 1, x, T); }}
FEN 2013-03-02 AK IT: Softwarekonstruktion 11
The Towers of Hanoi
• Three pins:– source, S– target, T– help, H
• 64 discs with decreasing diameters are to be moved from S to T observing the following rules:– A larger disc can not be placed upon a smaller– Only one disc can be moved at the time
Algorithm?
FEN 2013-03-02 AK IT: Softwarekonstruktion 12
The Towers of Hanoi• Solution:
– Move 63 discs from S to H using T as help– Move one disc from S to T– Move 63 discs from H to T using S as help
• Now the problem is how to move the 63 discs. That must be easier:– Move 62 discs…– Move one disc– Move 62 discs…
This yields a recursive solution
The Algorithm in C#public static void Hanoi(int n, char s, char h, char d){ //Moves n disks from S(ource) to D(estination) using H(elp) //Do not try this for n much larger 16 calls++; if (n == 1) { //System.Console.WriteLine("Move one disk from: " + s + " to:" + d); } else { Hanoi(n - 1, s, d, h); //System.Console.WriteLine("Move one disk from: " + s + " to:" + d); Hanoi(n - 1, h, s, d); }}
FEN 2013-03-02 AK IT: Softwarekonstruktion 13
FEN 2013-03-02 AK IT: Softwarekonstruktion 14
Efficiency of Recursive Algorithms
• Overhead in time due to call-return
• Overhead in space due to the recursion stack
• The Recursion Tree tells about complexity:– The depth tells about
memory space– The number of nodes tells
about running time
FEN 2013-03-02 AK IT: Softwarekonstruktion 15
Examples
• Draw the recursion trees:– Binary Search: O(log n) (time and space)– Factorial of n: O(n) (time and space)– Towers of Hanoi: O(2n) (time)
O(n) (space)
FEN 2013-03-02 AK IT: Softwarekonstruktion 16
Recursive vs. Iterative Algorithms
• It is always possible to rewrite a recursive algorithm to an equivalent iterative which may be more efficient. But the iterative version is often more complicated, since one has to handle the recursion stack oneself.
• In some cases it is possible to find iterative algorithms that are more efficient and as simple as the equivalent recursive:– Tail recursion:
• If the recursive call is the last statement in the algorithm, then there is no need for remembering the state of other active calls.
• The recursion can the be converted to a loop and there is no need for the recursion stack.
• Hence we get rid of the overhead to call-return and the overhead in space as well.