programming recursion “to iterate is human, to recurse, divine” -- l. peter deutsch

47
Programming Recursion “To Iterate is Human, to Recurse, Divine” -- L. Peter Deutsch

Post on 21-Dec-2015

222 views

Category:

Documents


3 download

TRANSCRIPT

Programming

Recursion

“To Iterate is Human, to Recurse, Divine”

--L. Peter Deutsch

Functions – Reminder

A group of variables and statements that is assigned a name

A sub-program A function may call other functions.

return-type name(arg_type1 arg_name1, arg_type2 arg_name2, …)

{

function body;

return value;

}

Return Statement - Reminder

Return causes the execution of the function to terminate and returns a value to the caller.

Scope of Variables - Reminder

A variable declared within a function is unrelated to variables declared elsewhere

A function cannot directly access variables that are declared in other functions

Function Declaration - Reminder

We can call a function from the point in the file in which the function has been declared, until the end of the file.

return-type name(arg_type1 arg_name1, arg_type2 arg_name2, …);

Recursive Function

A function defined in terms of itself is called a recursive function.

return_value rec_func(type arg1, type arg2, …){ … rec_func(…); …}

As we saw, n! = 1*2*3*… *(n-1)*n

Thus, we can also define factorial the following way: 0! = 1 n! = n*(n-1)! for n>0

(n-1)!* n

Factorial

A Recursive Definition

C functions can call themselves! However, not with the same parameters (why?)

Some functions can be defined using smaller occurrences of themselves.

Such a definition is called a “recursive definition” of a function.

Every recursive function must have a “boundary condition”. The function stops calling itself when it is satisfied. Why is this necessary?

Example - Factorial

int fact_rec(int n){ if (n == 0) return 1;

return n * fact_rec(n-1);}

int fact_itr(int n){ int fact = 1;

while (n >= 1) { fact *= n; --n; }

return fact;}

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← ?

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← ?

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * ?

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * ?

n ← 2return ← ?

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * ?

n ← 2return ← 2 * ?

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * ?

n ← 2return ← 2 * ?

n ← 1return ← ?

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * ?

n ← 2return ← 2 * ?

n ← 1return ← 1 * ?

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * ?

n ← 2return ← 2 * ?

n ← 1return ← 1 * ?

n ← 0return ← ?

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * ?

n ← 2return ← 2 * ?

n ← 1return ← 1 * ?

n ← 0return ← 1

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * ?

n ← 2return ← 2 * ?

n ← 1return ← 1 * 1

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * ?

n ← 2return ← 2 * 1

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * ?

n ← 3return ← 3 * 2

Recursive factorial

int fact_rec(int n)

{

if (n == 0)

return 1;

return n * fact_rec(n-1);

}

n ← 4return ← 4 * 6

Another Examplevoid print_nums(int num){ if (num == 0) return;

printf("%d ", num); print_nums(num - 1); printf("%d ", num);}

printcall funcprint

3

printcall funcprint

2

printcall funcprint

1

return 0

3 2 1 1 2 3

What Does It Do?

void foo(){ int num;

scanf("%d", &num); if (num < 0) return;

foo(); printf("%d ", num);}

Reverse Print

void reverse_print(){ int num;

scanf("%d", &num); if (num < 0) return;

reverse_print(); printf("%d ", num);}

Reads an unbounded series of numbers from the user and prints them in reverse order.

Power

xy = x*x*…*x

Recursive definitions (assume non-negative y): 1, y = 0 xy= x*xy-1, y odd (xy/2)2, y even

y times

rec_pow

int rec_pow(int x, int y){ if (y == 0) return 1; if (y % 2 != 0) return x * rec_pow(x, y - 1); else return square(rec_pow(x, y / 2));}

The Three Rules of Recursion

1. Know when to stop.

2. Decide how to take one step.

3. Break the problem down into that step plus a smaller problem.

Exercise

Write a program that receives two non-negative integers and computes their product recursively.

Hint: Notice that the product a*b is actually a+a+…+a (b times).

Solution

int rec_mul(int a, int b)

{

/* base condition – a * 0 = 0 */

if (b == 0)

return 0;

/* save a and call recursively */

return a + rec_mul(a, b-1);

}

Exercise

Given the following iterative version of sum-of-digits calculation

Find the recursive definition of this function

(don’t forget the base case!)

int sum_digits(int n){

int sum = 0;while (n > 0) {

sum += n%10;n = n/10;

}return sum;

}

Solution

int sum_digit_rec(int n)

{

if (n == 0) return 0;

return n % 10 + sum_digit_rec(n / 10);

}

More uses

Recursion is a general approach to programming functions

Its uses are not confined to calculating mathematical expressions!

For example – max_rec.c

Step By Step

int max_rec(int *arr, int size){ int rest_max;

if (size == 1) return *arr;

rest_max = max_rec(arr + 1, size - 1); if (*arr > rest_max) return *arr; else return rest_max;}

1 4 7 2arr:

max_rec( , 4)

rest_max =

max_rec( , 3)

rest_max =

max_rec( , 2)

rest_max =

max_rec( , 1)

rest_max =

2

7

7

What Does It Do?

char *rec_func(char *str, char c){if (*str == '\0')

return NULL;

if (*str == c)return str;

return rec_func(++str, c);}

Solution

A recursive implementation of strchr

Exercise

Give a recursive implementation to int strcmp(const char *s, const char *t);

The function compares two strings and return: 0 – if s == t negative – if s < t positive – if s > t

Write a program that accepts two strings from the user and compare them using the above function

Solution

int strcmp(cons char *s, const char *t){ if (*s != *t) return *s - *t;

if (*s == '\0') return 0;

return strcmp(++s, ++t);}

Towers of Hanoi

Initial Setup:Tower A contains n disks of different sizes.Disks can only go on top of smaller disks (or

directly on the board).

A CB

Towers of Hanoi

Objective:Move all n disks from tower A to tower C.

A CB

Towers of Hanoi

Moves:Take the top disk of a tower and move the

disk to another tower.No disk may be put on top of a smaller disk.

A CB

Towers of Hanoi

Move tower with n disks is equivalent to:1. Move tower with n-1 disks

A CB

Towers of Hanoi

Move tower with n disks is equivalent to:2. Move a single disk

A CB

Towers of Hanoi

Move tower with n disks is equivalent to:3. Move tower with n-1 disks

A CB

Towers of Hanoi - C

void move_disk(char from, char to){ printf("move disk from %c to %c\n", from, to);}

void move_tower(int height, char from, char to, char temp){ if (height == 1) { move_disk(from, to); } else { move_tower(height - 1, from, temp, to); move_disk(from, to); move_tower(height - 1, temp, to, from); }}