340 likes | 777 Views
Recursion. Recursion is a technique that solves a problem by solving a smaller problem of the same type. A recursive function is a function invoking itself, either directly or indirectly. Recursion can be used as an alternative to iteration.
E N D
Recursion • Recursion is a technique that solves a problem by solving a smaller problem of the same type. • A recursive function is a function invoking itself, either directly or indirectly. • Recursion can be used as an alternative to iteration. • Recursion is an important and powerful tool in problem solving and programming. • Recursion is a programming technique that naturally implements the divide-and-conquer problem solving methodology. CS102 Algorithms and Programming II
The Nature of Recursion • One or more simple cases of the problem (called the stopping cases or base case) have a simple non-recursive solution. • The other cases of the problem can be reduced (using recursion) to problems that are closer to stopping cases. • Eventually the problem can be reduced to stopping cases only, which are relatively easy to solve. In general: if (stopping case) solve it else reduce the problem using recursion CS102 Algorithms and Programming II
Four Criteria of A Recursive Solution • A recursive function calls itself. • This action is what makes the solution recursive. • Each recursive call solves an identical, but smaller, problem. • A recursive function solves a problem by solving another problem that is identical in nature but smaller in size. • A test for the base case enables the recursive calls to stop. • There must be a case of the problem (known as base case or stopping case) that is handled differently from the other cases (without recursively calling itself.) • In the base case, the recursive calls stop and the problem is solved directly. • Eventually, one of the smaller problems must be the base case. • The manner in which the size of the problem diminishes ensures that the base case is eventually is reached. CS102 Algorithms and Programming II
Four Questions for Constructing Recursive Solutions • How can you define the problem in terms of a smaller problem of the same type? • How does each recursive call diminish the size of the problem? • What instance of the problem can serve as the base case? • As the problem size diminishes, will you reach this base case? CS102 Algorithms and Programming II
Factorial Function – Iterative Definition n! = n * (n-1) * (n-2) * … * 2 * 1 for any integer n>0 0! = 1 Iterative Definition fval = 1; for (i = n; i >= 1; i--) fval = fval * i; CS102 Algorithms and Programming II
Factorial Function - Recursive Definition • To define n! recursively, n! must be defined in terms of the factorial of a smaller number. • Observation (problem size is reduced): n! = n * (n-1)! ( a recurrence relation) • Base case: 0! = 1 • We can reach the base case, by subtracting 1 from n if n is a positive integer. Recursive Definition: n! = 1 if n = 0 n! = n * (n-1)!if n > 0 CS102 Algorithms and Programming II
Factorial Function - Recursive Definition in C++ static int fact(int n) // Computes the factorial of a nonnegative integer. // Precondition: n must be greater than or equal to 0. // Postcondition: Returns the factorial of n; n is unchanged. { if (n ==0) return (1); else return (n * fact(n-1)); } • This fact function satisfies the four criteria of a recursive solution. CS102 Algorithms and Programming II
A Sequence of Computations of Factorial Function CS102 Algorithms and Programming II
A Recursive void Function – Writing a String Backward Problem: Write the given string of characters in reverse order. Recursive Solution: Base Case: Write the empty string backward. Recursive Case: How can we write an n-character string backward, if we can write an (n-1)-character string backward? • Strip away the last character, or strip away the first character writeBackward(s:string) if (the string s is empty) Do nothing // base case else { Write the last character of s writeBackward(s minus its last character) } CS102 Algorithms and Programming II
Writing a String Backward static void writeBackward(String s, int size) // Writes a character string backward. // Precondition: The string s contains size characters, where size >= 0. // Postcondition: s is written backward, but remains unchanged. { if (size > 0) { // write the last character System.out.print(s.charAt(size-1)); // write the rest of the string backward writeBackward(s, size-1); // Point A } // end if // size == 0 is the base case - do nothing } // end writeBackward CS102 Algorithms and Programming II
Vertical Numbers • The static recursive methodwriteVertical takes one (nonnegative) int argument, and writes that int with the digits going down the screen one per line • Note: Recursive methods need not be static • This task may be broken down into the following two subtasks • Simple case: If n<10, then write the number n to the screen • Recursive Case: If n>=10, then do two subtasks: • Output all the digits except the last digit • Output the last digit CS102 Algorithms and Programming II
Vertical Numbers • Given the argument 1234, the output of the first subtask would be: 1 2 3 • The output of the second part would be: 4 • The decomposition of tasks into subtasks can be used to derive the method definition: • Subtask 1 is a smaller version of the original task, so it can be implemented with a recursive call • Subtask 2 is just the simple case CS102 Algorithms and Programming II
Vertical Numbers public static void writeVertical(int n){ if (n < 10){ System.out.println(n); } else //n is two or more digits long: { writeVertical(n/10); System.out.println(n%10); } } CS102 Algorithms and Programming II
Binary Search public static int search(int[] a, int first, int last, intkey){ int result = 0; if (first > last) result = -1; else{ int mid = (first + last)/2; if (key == a[mid]) result = mid; else if (key < a[mid]) result = search(a, first, mid - 1, key); else if (key > a[mid]) result = search(a, mid + 1, last, key); } return result; } CS102 Algorithms and Programming II
The Towers of Hanoi Problem: • There are n disks and three poles: A(source), B(destination), C(spare) • The disks are of different sizes and they had holes in the middle so that they can fit on the poles. • The disks can be placed only top of disks larger than themselves. • Initially, all the disks are on pole A. • The disks can be moved one by one • At each move, only one disk can be moved from one pole to another without putting a larger disk on the top of a smaller disk. ? Move all n disks from pole A (source) to pole B (destination) • Find all required disk movements. CS102 Algorithms and Programming II
The Towers of Hanoi (cont.) initial state move n-1 disks from A to C CS102 Algorithms and Programming II
The Towers of Hanoi (cont.) move 1 disk from A to B move n-1 disks from C to B CS102 Algorithms and Programming II
The Towers of Hanoi – Recursive Solution solveTowers(count, source, destination, spare) if (count is 1) move a disk directly from source to destination else { solveTowers(count-1, source, spare, destination) solveTowers(1, source, destination, spare) solveTowers(count-1, spare, destination, source) } • This recursive solution to the Towers problem satisfies the four criteria of a recursive solution. CS102 Algorithms and Programming II
The Order of Recursive Calls of solveTowers(3,A,B,C) – Recursion Tree CS102 Algorithms and Programming II
The Solution for Three Disks • Move top disk from pole A to pole B • Move top disk from pole A to pole C solveTowers(2,A,C,B) • Move top disk from pole B to pole C • Move top disk from pole A to pole B • Move top disk from pole C to pole A • Move top disk from pole C to pole B solveTowers(2,C,B,A) • Move top disk from pole A to pole B } } CS102 Algorithms and Programming II
The Towers of Hanoi void solveTowers(int count, char source, char destination, char spare) { if (count == 1) { System.out.println( "Move top disk from pole " +source+ " to pole " +destination ); } else { solveTowers(count-1, source, spare, destination); // X solveTowers(1, source, destination, spare); // Y solveTowers(count-1, spare, destination, source); // Z } // end if } // end solveTowers CS102 Algorithms and Programming II
Recursion and Efficiency • Recursion is a powerful problem-solving technique that often produces very clean solutions to even most complex problems. • Recursive solutions can be easier to understand and to describe than iterative solutions. • But some recursive solutions are inefficient. • factorial, writeBackward functions are inefficient. • We can have efficient iterative versions of these recursive solutions. • We shouldn’t use a recursive solution if it is inefficient and we have a clear, efficient iterative solution. • Recursion is truly valuable when a problem has no simple iterative solution. CS102 Algorithms and Programming II
Comparison of Iteration and Recursion • In general, an iterative version of a program will execute more efficiently in terms of time and space than a recursive version. • This is because the overhead involved in entering and exiting a function is avoided in iterative version. • The inherent inefficiency of some recursive algorithms. • However a recursive solution can be sometimes the most natural and logical way of solving a problem. • Conflict: machine efficiency versus programmer efficiency. • It is always true that a recursive solution can be replaced with an iterative solution using a stack. • If a recursive solution is inefficient, we can convert that recursive solution to an efficient iterative solution. CS102 Algorithms and Programming II
writeBackward void writeBackward(String s, int size) { // Recursive version if (size > 0) { System.out.print(s.charAt(size-1)); writeBackward(s, size-1); } } ---------------------------------------------------------------------------------------------- void writeBackward(String s, int size) { // Iterative version. while (size > 0) { System.out.print(s.charAt(size-1)); --size; } } CS102 Algorithms and Programming II
Iterative Binary Search public static int search(int[] a, int lowEnd, int highEnd, int key){ int first = lowEnd; int last = highEnd; int mid; boolean found = false; int result = 0; while ( (first <= last) && !(found) ) { mid = (first + last)/2; if (key == a[mid]) {found = true;result = mid; } else if (key < a[mid]) last = mid - 1; else if (key > a[mid])first = mid + 1; } if (first > last) result = -1; return result; } CS102 Algorithms and Programming II