Recursion Introduction What does the program do include

  • Slides: 35
Download presentation
Recursion

Recursion

Introduction What does the program do? #include <iostream> using namespace std; int fac(int n){

Introduction What does the program do? #include <iostream> using namespace std; int fac(int n){ int product; if(n <= 1) product = 1; else product = n * fac(n-1); return product; } void main(){ int number; cout << "Enter a positive integer : " << endl; ; cin >> number; cout << fac(number) << endl; }

Trace it … Assume the number typed is 3. fac(3): has the final returned

Trace it … Assume the number typed is 3. fac(3): has the final returned value 6 3<=1 ? No. product 3 = 3*fac(2) product 3=3*2=6, return 6, fac(2): 2<=1 ? No. product 2 = 2*fac(1) product 2=2*1=2, return 2, fac(1): 1<=1 ? Yes. return 1

Normal (non-recursive) functions Recursive function int main() { one(…); } int main() { fac(3);

Normal (non-recursive) functions Recursive function int main() { one(…); } int main() { fac(3); } void one(…) { … two(…) … } int fac(int n){ int product; if(n <= 1) product = 1; else product = n * fac(n-1); return product; void two(…) { … three(…) … } } void three(…) { … } l l Functions are calling DIFFERENT functions One function (three) is the last ‘stopping function’ l l … calling the SAME function (with different parameters) … The ‘stopping function’ is already included as a ‘condition’

Recursive function A recursive function is just a function which is calling one (or

Recursive function A recursive function is just a function which is calling one (or more) other functions which happen to be the same!!! l l Though the function is the same, the ‘parameters’ are always different and ‘smaller’. There is always at least one stopping case to terminate. It is a kind of ‘loop’, even more powerful as a general problem-solving technique! --- thinking recursively!

Recursion: problem solving, therefore a programming technique Remember: The general top-down programming and problem

Recursion: problem solving, therefore a programming technique Remember: The general top-down programming and problem solving: A complex problem is often easier to solve by dividing it into several smaller parts (by top-down analysis), each of which can be solved by itself. * * * Recursion is one way to decompose a task into smaller subtasks. At least one of the subtasks is a smaller example of the same task. The smallest example of the same task has a non-recursive solution. Example: The factorial function n! = n * (n-1) * (n-2) *. . . * 1 or n! = n * (n-1)! and 1! = 1

Recursion vs. Iteration (non-recursive) * A recursive solution may be simpler to write (once

Recursion vs. Iteration (non-recursive) * A recursive solution may be simpler to write (once you get used to the idea) than a non-recursive solution. * But a recursive solution may not be as efficient as a nonrecursive solution of the same problem. To iterate is human, to recurse, divine!

Iterative Factorial // Non-recursive factorial function // Compute the factorial using a loop int

Iterative Factorial // Non-recursive factorial function // Compute the factorial using a loop int fac(int n){ int k, product; if(n <=1) product = 1; for(k=1; k<=n; k++) product = k*product; return product; }

Other recursive examples * Fibonacci numbers: 0, 1, 1, 2, 3, 5, 8, 13,

Other recursive examples * Fibonacci numbers: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, . . . where each number is the sum of the preceding two. * Recursive definition: F(0) = 0 n F(1) = 1 n F(n) = F(n-1) + F(n-2) n

Everything is recursive … Linear search Length of a string Min, max of an

Everything is recursive … Linear search Length of a string Min, max of an array Selection sort Bubble sort … Binary search: Compare search element with middle element of the array: n If not equal, then apply binary search to half of the array (if not empty) where the search element would be. n

For n elements in an array: Start from the first element while (not yet

For n elements in an array: Start from the first element while (not yet finished) do the current element move to the next one do-something(n) If 0 or 1 element, just do it else (decompose into first element and the n-1 remaining elements) do the first element do-something(n-1)

Sum of an array Write a recursive function that computes the sum of all

Sum of an array Write a recursive function that computes the sum of all elements in an array of integers. What is the summation of n elements? int summation(int a[], int size){ int sum; if(size==0) sum=0; else sum=summation(a, size-1)+a[size-1]; return sum; }

Product of an array Write a recursive function that computes the product of an

Product of an array Write a recursive function that computes the product of an array of integers. What is the product of n elements? int product(int a[], int size) { int prod; if(size==0) prod=1; else prod=product(a, size-1)*a[size-1]; return prod; }

Recursion general form How to write recursively? function-type function(parameters) { function-type value; if(stopping conditions)

Recursion general form How to write recursively? function-type function(parameters) { function-type value; if(stopping conditions) value = stopping value; else value = g(function((revised parameters))); return value; }

Exponential How to write exp(int x, int y) recursively? int exp(int x, int y)

Exponential How to write exp(int x, int y) recursively? int exp(int x, int y) { int power; if(y==0) power = 1; else power = x * exp(x, y-1); return power; }

Counting the number of zeros * * Write a recursive function that counts the

Counting the number of zeros * * Write a recursive function that counts the number of zero digits in a non-negative integer zeros(10200) returns 3 int zeros(int n){ int z; if (n<10) if (n==0) z=1; else z=0; else z=zeros(n/10)+zeros(n%10); } l l return z; n/10 the number n with the last digit removed n%10 the last digit of n

Find factors Write a recursive function to determine how many factors m are part

Find factors Write a recursive function to determine how many factors m are part of n. For example, if n=48 and m=4, then the result is 2 (48=4*4*3). int factors(int n, int m){ int f; if(n%m != 0) f=0; else f=1+factors(n/m, m); return f; }

Summary natural consequence of ‘top-down’ analysis * ‘everything’ is recursive * * Decomposition-composition *

Summary natural consequence of ‘top-down’ analysis * ‘everything’ is recursive * * Decomposition-composition * Let’s trace a few examples … zeros(123009840) n asum(A, 5) n exp(6, 4) n … n

A more subtle example: the max of an array max(n): start from the first

A more subtle example: the max of an array max(n): start from the first element: max=the-first while (not yet finished) pick up new-element max=maximum. Of. Two(max, new-element) move to the next element if one-element, max = one-element else decompose n elements into: 1 -element and n-1 element m 1 = the 1 -element m 2 = max(n-1) compose the final solution: max = maximum. Of. Two(m 1, m 2) int max 2(int m 1, int max 2) {return (m 1>m 2)? m 1: m 2; }; int max(int A[], int n) { int max=A[0]; int i=1; while (i<n) { max=max 2(max, A[i]); i=i+1; } return max; } int max 2(int m 1, int max 2) {return (m 1>m 2)? m 1: m 2; }; int max(int A[], int size) { int max, m 2; if (size==1) max=A[size-1]; else m 2=max(A, size-1); max=max 2(A[size-1], m 2); return max; }

Efficiency int max 2(int m 1, int max 2) {return (m 1>m 2)? m

Efficiency int max 2(int m 1, int max 2) {return (m 1>m 2)? m 1: m 2; }; int max(int A[], int size) { int max; if (size==1) max=A[size-1]; else max=max 2(max(A, size-1), A[size-1]); return max; } int max(int A[], int size) { int max; if (size==1) max=A[size-1]; else if(max(A, size-1)>A[size-1])) max=max(A, size-1); else max=A[size-1]; return max; } int max(int A[], int size) { if (size==1) return A[size-1]; else if(max(A, size-1)>A[size-1])) return max(A, size-1); else return A[size-1]; } The same code, but no intermediate storage ‘m 2’, it will have more recursive calls … inefficient!

Fibonacci (quite inefficient) int fibonacci(int n) { int f; if(n==0) f=0; else if (n==1)

Fibonacci (quite inefficient) int fibonacci(int n) { int f; if(n==0) f=0; else if (n==1) f=1; else f= fibonacci(n-1)+fibonacci(n-2); return f; } How many calls?

(Iterative) Fibonacci int fibonacci(int n) { int fib; int fibm 1=1; int fibm 2=0;

(Iterative) Fibonacci int fibonacci(int n) { int fib; int fibm 1=1; int fibm 2=0; if(n==0) fib=0; else if (n==1) fib=1; int j; for(j=2; j<=n; j++) { fib=fibm 1+fibm 2; fibm 2=fibm 1; fibm 1=fib; } return fib; }

Linear search Input: an array of integers A, and a value Output: the position

Linear search Input: an array of integers A, and a value Output: the position of the value in the array if one element, check it! else decompose into 1 -element and n-1 elements check the 1 -element search(n-1)

int search(int A[], int size, int value) { int pos; if (size==1) if(A[size-1]==value) pos=1;

int search(int A[], int size, int value) { int pos; if (size==1) if(A[size-1]==value) pos=1; else pos=-1; else if(A(size-1]==value) pos=size-1; else pos=search(A, size-1, value); return pos; }

(Binary) Search in a sorted array Input: a sorted array of integers A, and

(Binary) Search in a sorted array Input: a sorted array of integers A, and a value Output: the position of the value in the array

Binary search Input: a sorted array of integers A, and a value Output: the

Binary search Input: a sorted array of integers A, and a value Output: the position of the value in the array if the middle element == value, done! else if the middle element > value do the same in the first half of the array else do the same in the second half of the array }

int bsearch(int data[], lower, upper, value) { int pos; if (lower<=upper) { mid=(lower+upper)/ 2;

int bsearch(int data[], lower, upper, value) { int pos; if (lower<=upper) { mid=(lower+upper)/ 2; if (data[mid] == value) pos=mid; else if (data[mid]>value) pos=bsearch(data, lower, mid– 1, value); else pos=bsearch(data, mid+1, upper, value); } } return pos;

(iterative) Binary search: int bsearch(int data[], int size, int value) { int lower, middle,

(iterative) Binary search: int bsearch(int data[], int size, int value) { int lower, middle, upper; bool found; lower = 0; upper = size - 1; found=false; position=-1; while ((lower<=upper) && (!found)) { middle = (lower+upper)/2; if (data[middle] == value) { found=true; position=middle; } else { if (data[middle] > value) upper = middle - 1; else lower = middle + 1; } } } return position; int main() { const int size=8; int data[size] = {1, 5, 6, 7, 9, 10, 17, 30}; int value; cin >> value; cout << “position of the value is “ << bsearch(data, size, value) << endl; }

The tower of Hanoi! Move a stack of disks of different sizes from one

The tower of Hanoi! Move a stack of disks of different sizes from one rod to another through a third one: - only one disk is moved each time - always smaller ones on top of bigger ones Check any webpage!

// move n disks from A to C via B void tower(int n, char

// move n disks from A to C via B void tower(int n, char A, char B, char C) { if (n==1) move(1, A, C); else {tower(n-1, A, C, B); move(n, A, C); tower(n-1, B, A, C)}; } void move(int k, char X, char Y) { cout << “move disc ” << k << “ from “ << X << “ to “ Y “ << endl; }

trace tower(3, A, B, C) …

trace tower(3, A, B, C) …

There are systematic ways of de-recursing a function l Hanoi tower is easy to

There are systematic ways of de-recursing a function l Hanoi tower is easy to write in recursive form, l but very hard to write in iterative from! l l. LISP l l (scheme) language (for AI, Fortran for computing): functional programming language intrinsically recursive (loops are rarely used)

For n elements in an array: Start from the first element While (not yet

For n elements in an array: Start from the first element While (not yet finished) do the current element move to the next one Do. Sth(n) If 0 or 1 element, just do it else decompose into first element and the n-1 remaining elements (trivially) do the first element Do. Sth(n-1) compose the solution of n elements

Palindrome in an array of integers or character of known size…

Palindrome in an array of integers or character of known size…

bool palindrom(int a[], lower, upper) { bool pal=false; if (lower>=upper) pal=true; else pal=(a[lower]==a[upper]) &&

bool palindrom(int a[], lower, upper) { bool pal=false; if (lower>=upper) pal=true; else pal=(a[lower]==a[upper]) && palindrom(a, lower+1, upper-1); } return pal; int main() { … palindrom(a, 0, 10); … }