Recursion A recursive function is a function that

  • Slides: 29
Download presentation
Recursion • A recursive function is a function that calls itself either directly or

Recursion • A recursive function is a function that calls itself either directly or indirectly through another function. • The problems that can be solved by recursion must have the following characteristics: - One or more simple cases of the problem have a straightforward, nonrecursive solution. - The other cases can be redefined in terms of problems that are closer to the simple cases. - By applying this redefinition process every time the recursive function is called, eventually the problem is reduced entirely to simple cases, which are relatively easy to solve.

Recursion Recursive algorithm: if this is a simple case solve it else redefine the

Recursion Recursive algorithm: if this is a simple case solve it else redefine the problem using recursion Problem: Multiply 6 by 3. The problem can be split into two problems: - 1. Multiply 6 by 2. - 2. Add 6 to the result of problem 1. Now we can solve problem 2 because we know our addition tables. But we cannot solve problem 1. Problem 1 is closer to the simple case than the original problem was. The recursive approach splits one size-n problem into n size-1 problems.

Recursion Problem: Multiply 6 by 3. The problem can be split into two problems:

Recursion Problem: Multiply 6 by 3. The problem can be split into two problems: - 1. Multiply 6 by 2. - 2. Add 6 to the result of problem 1. We can split problem 1 into two problems: - 1. 1 Multiply 6 by 1 - 1. 2 Add 6 to the result of problem 1. 1 Problem 1. 1 is the simple case. We can solve it because we know that any number multiplied by 1 gives us the original number. Here, we assumed that we know our addition tables. We can solve problem 1. 2. So, problem 1 is solved. We have already solved Problem 2. Therefore, we have solved the problem.

Recursive function multiply // Performs integer multiplication using + operator. // Pre: m and

Recursive function multiply // Performs integer multiplication using + operator. // Pre: m and n are defined and n > 0 int multiply ( int m, int n ) { int ans; if (n == 1) ans = m; // simple case else ans = m + multiply ( m, n -1 ); // recursive step return (ans); }

Count the # of vowels in a string #include <stdio. h> #include < string.

Count the # of vowels in a string #include <stdio. h> #include < string. h> int count_vowel (char *input); int main() { char line[] = “Hello”; int num, count; printf(“num of vowels are %dn”, count_vowels(line); return 0; }

Count the # of vowels in a string int count_vowels (char *string_ptr) { if

Count the # of vowels in a string int count_vowels (char *string_ptr) { if (*str_ptr == ‘’) return 0; // simple case else { switch (*string_ptr) { // redefine problem using recursion case ‘a’ : case ‘e’ : case ‘i’ : case ‘o’ : case ‘u’: return (1 + count_vowels ( string_ptr + 1)); break; default : return count_vowels (string_ptr + 1); break; } }

18 Tracing a Recursive Function • Multiply(6, 3) m = 6, n = 3

18 Tracing a Recursive Function • Multiply(6, 3) m = 6, n = 3 3 == 1 is false ans is 6 + multiply(6, 2) return (ans) 12 Three activation frames corresponding to each call of the function are generated to solve the problem. m = 6, n = 2 2 == 1 is false ans is 6 + multiply(6, 2) return (ans) 6 m = 6, n = 1 1 == 1 is true ans is 6 return (ans)

Function reverse_input_words void reverse_input_words(int n) { char word[WORDSIZ]; if (n <= 1) // simple

Function reverse_input_words void reverse_input_words(int n) { char word[WORDSIZ]; if (n <= 1) // simple case { scanf(“%s”, word); printf(“%sn”, word); } else // get and print the rest of the words { // in reverse order and print it. scanf(“%s”, word); reverse_input_words(n - 1); printf(“%sn”, word); }

Tracing a Void Recursive Function • Reverse_input_words (3) n = 3 ** 3 <=

Tracing a Void Recursive Function • Reverse_input_words (3) n = 3 ** 3 <= 1 is false scan “how” into word reverse_input_words(2) display “how” return Three activation frames corresponding to each call of the function are generated to solve the problem. n = 2 ** 2 <= 1 is false scan “are” into word reverse_input_words(1) display “are” return ** word is undefined A void function’s return occurs when the closing brace of the function body is encountered. n = 1 ** 1 <= 1 is true scan “you” into word display “you” return

Sequence of Events for the Function Call reverse_input_words with n = 3. Scan the

Sequence of Events for the Function Call reverse_input_words with n = 3. Scan the first word (“How”) into word. Call reverse_input_words with n = 2. Scan the second word (“are”) into word. Call reverse_input_words with n = 1. Scan the third word (“you”) into word. Display the third word (”you”). Return from third call. Display the second word (“are”). Return from second call. Display the first word (“How”). Return from the original call.

Parameter and Local Variable Stack • C uses the stack data structure to keep

Parameter and Local Variable Stack • C uses the stack data structure to keep track of the values of n and word at any given point. • In this structure, we add data items and remove them from the same end of the list. • The last item stored is the first processed. • When executes a call to the function, the system pushes the parameter value on the top of the parameter stack. • Pushes a new undefined cell on top of the stack maintained for the local variable word. • A return from the function pops each stack, removing the top value.

Example ? • After first call to reverse_input_words 3 • The word “How” is

Example ? • After first call to reverse_input_words 3 • The word “How” is stored in word just before the second call 3 How • After the second call. 2 ? 3 How • The word “are” is scanned and stored in word just before third call are 2 How 3 • After the third call 1 2 3 ? are How 1 2 3 you are How

Example • During the execution of the function, the word “you” is scanned and

Example • During the execution of the function, the word “you” is scanned and stored in word, and “you”is printed immediately because n =1 1 you 2 are 3 How • The function return pops both stacks. After the first return: 2 3 Are How 3 How • After the second return • The third and last return exits the original function call. So there is no longer memory allocated for n and word.

System Stack • We have used separate stacks for each parameter in the example.

System Stack • We have used separate stacks for each parameter in the example. • The compiler actually maintains a single system stack • Whenever a call to a function occurs, all its parameters and local variables are pushed onto the stack along with the memory address of the calling statement. • This address gives the computer the return point after execution of the function. • Multiple copies of a function’s parameters may be saved on the stack, only one copy of the function body is in memory.

Recursive factorial Function // Compute n! using recursion !1 = 1 // Pre: n

Recursive factorial Function // Compute n! using recursion !1 = 1 // Pre: n >= 0 !4 = 4 * !3 int factorial (int n) = 4 * 3 * !2 = 4 * 3 * 2 * !1 { =4*3*2*1 int ans; = 24 if (n == 0) // simple case ans = 1; else // redefine problem using recursion ans = n * factorial (n - 1); return (ans); }

Recursive fibonacci Function // Compute the nth Fibonacci number using recursion // Pre: n

Recursive fibonacci Function // Compute the nth Fibonacci number using recursion // Pre: n >= 0 int fibonacci (int n) Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, …. { int ans; if (n == 1 || n == 2) // simple case ans = 1; else // redefine problem using recursion ans = fibonacci(n - 2) + fibonacci (n - 1); return (ans); }

Towers of Hanoi • Towers of Hanoi problem involves moving a specified number of

Towers of Hanoi • Towers of Hanoi problem involves moving a specified number of disks that are all different sizes from one tower (or peg) to another. • Problem: Move n disks from peg A to peg C using peg B as an intermediate peg. • Conditions: 1. 2. Only one disk at a time may be moved, and this disk must be the top disk on a peg. A larger disk cannot be placed on top of a smaller disk.

Tower of Hanoi Start 1 2 3 (A) (B) (C) Goal (A) (B) (C)

Tower of Hanoi Start 1 2 3 (A) (B) (C) Goal (A) (B) (C)

Tower of Hanoi 1 (A) (B) (C) Simple case: single disk. Just move the

Tower of Hanoi 1 (A) (B) (C) Simple case: single disk. Just move the disk 1 from peg A to peg C

Tower of Hanoi Top (n - 1) disks 1 2 3 (A) (B) (C)

Tower of Hanoi Top (n - 1) disks 1 2 3 (A) (B) (C) Move the top (n -1) disks from peg A to peg B. (A) (B) (C)

Tower of Hanoi 1 (A) (B) (C) Move the bottom disk (1) from peg

Tower of Hanoi 1 (A) (B) (C) Move the bottom disk (1) from peg A to peg C. (A) (B) (C)

Tower of Hanoi Top (n - 1) disks (A) (B) (C) Move the top

Tower of Hanoi Top (n - 1) disks (A) (B) (C) Move the top (n - 1) disks from peg B to peg C. (A) (B) (C)

Data Requirements • Problem Inputs: int n char from_peg char to_peg char aux_peg •

Data Requirements • Problem Inputs: int n char from_peg char to_peg char aux_peg • Problem Outputs: A list of instructions for moving n disks from_peg to to_peg using aux_peg as an intermediate peg.

Algorithm 1. if n is 1 then 2. Move disk 1 from the from_peg

Algorithm 1. if n is 1 then 2. Move disk 1 from the from_peg to the to_peg. else 3. Move n - 1 disks from the from_peg to the auxiliary peg using the to_peg. 4. Move disk n from the from_peg to the to_peg. 5. Move n - 1 disks from the auxiliary peg to the to_peg using the from_peg.

Recursive Function Tower // Displays instruction for moving n disks from_peg to to_peg //

Recursive Function Tower // Displays instruction for moving n disks from_peg to to_peg // using aux_peg as an intermediate peg. void tower ( char from_peg, char to_peg, char aux_peg, int n) { if (n == 1) // simple case printf(“Move disk 1 from peg %c to peg %cn”, from_peg, to_peg); else // redefine the problem using recursion { tower(from_peg, aux_peg, to_peg, n -1); printf(“Move disk %d from peg %c to peg %cn”, n, from_peg, to_peg); tower(aux_peg, to_peg, from_peg, n - 1); }

Output of tower Function Output generated by tower (‘A’, ‘C’, ‘B’, 3): Move disk

Output of tower Function Output generated by tower (‘A’, ‘C’, ‘B’, 3): Move disk 1 from A to C Move disk 2 from A to B Move disk 1 from C to B Move disk 3 from A to C Move disk 1 from B to A Move disk 2 from B to C Move disk 1 from A to C n - disk problem requires 2 n - 1 moves.

Recursion Vs. Iteration • Both iteration and recursion are based on a control structure:

Recursion Vs. Iteration • Both iteration and recursion are based on a control structure: iteration uses a repetition structure and recursion uses a selection structure. • Both iteration and recursion involve repetition. Iteration explicitly uses a repetition structure and recursion achieves repetition through repeated function calls. • Iteration and recursion each involve a termination test. Iteration terminates when the loop-continuation condition fails. Recursion terminates when the base case is reached. • Both iteration and recursion can occur infinitely. An infinite loop can occurs with iteration if the loop-continuation test never becomes false. Infinite recursion occurs if the recursive step does not reduce the problem each time in a manner that converges on the base case.

Recursion Vs. Iteration • Recursion has many negatives. It repeatedly invokes the mechanism, and

Recursion Vs. Iteration • Recursion has many negatives. It repeatedly invokes the mechanism, and consequently the overhead, of function calls. This can be expensive in both processor time and memory space. . • Each recursive call causes another copy of the function (actually only the function’s variables) to be created. This can consume considerable memory. • Iteration normally occurs within a function so the overhead of repeated function calls and extra memory assignment is omitted. • So why choose recursion? • In many instances, the use of recursion enables us to specify a very natural, simple solution to a problem that would otherwise be very difficult to solve (e. g. Tower of Hanoi). • For this reason, recursion is an important and powerful tool in problem solving and programming.