Recursion: Programming Technique in Which A Method (Function) Calls Itself
The document discusses recursion, which is a programming technique where a method calls itself. It provides examples of recursively calculating triangular numbers and factorials. Recursion simplifies problems conceptually but is less efficient than iteration due to overhead from method calls and potential for stack overflows. The document also covers binary search and quicksort algorithms implemented recursively and iteratively.
Download as PPT, PDF, TXT or read online on Scribd
0 ratings0% found this document useful (0 votes)
33 views
Recursion: Programming Technique in Which A Method (Function) Calls Itself
The document discusses recursion, which is a programming technique where a method calls itself. It provides examples of recursively calculating triangular numbers and factorials. Recursion simplifies problems conceptually but is less efficient than iteration due to overhead from method calls and potential for stack overflows. The document also covers binary search and quicksort algorithms implemented recursively and iteratively.
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 23
Recursion
Programming technique in which a
method (function) calls itself Triangular Numbers What is x in the series? 1, 3, 6, 10, 15, 21, x Also called triangular numbers
#1 = 1 #2 = 3 #3 = 6 #4 = 10 and so on Triangular Numbers Suppose you wanted to find the value of some arbitrary n-th term in the series; say the 4 th term (whose value is 10). How would you calculate it? Triangular Numbers You might decide that the value of any term can be obtained by adding up all the vertical columns of squares 4 + 3 + 2 + 1 = 10 Procedural Programming int triangle(int n) { int total = 0
while(n > 0) // until n is 1 { total = total + n; // add n (column height) to total --n; // decrement column height } return total } Recursive Programming The value of the n-th term can be thought of as the sum of only 2 things, instead of a whole series. These are: 1. The first (tallest) column, which has the value n 2. The sum of all the remaining columns 4 + 6 in the remaining columns = 10 Recursive Programming int triangle (int n) { return (n + sumRemainingColumns(n)); } If we knew a method that found the sum of all remaining columns: Recursive Programming int triangle (int n) { return (n + SumAllColumns(n-1)); } sumRemainingColumns (n) = sumAllColumns(n-1) Recursive Programming sumAllColumns( ) = triangle ( ) int triangle (int n) { return (n + triangle(n-1)); } Recursion : Passing the Buck Someone tells me to find the 4 th triangular number I know this is 4 plus the 3 rd triangular number I call Harry and ask him to find the 3 rd triangular number Harry knows that the 3 rd triangular number is 3 plus the 2 nd
triangular number Harry calls Jane and asks her to find the 2 nd triangular number Jane knows that the 2 nd triangular number is 2 plus the 1 st
triangular number (which is 1) The buck-passing must end at some point. Otherwise, the method would call itself over and over in an infinite series that would paralyse the program The Buck Stops Here The person who is asked to find the 1 st triangular number (when n = 1), must know the answer without asking anyone else. He knows the answer is 1. Every recursive method must have a base case to prevent infinite recursion int triangle (int n) { if(n == 1) // base case return 1; else return (n + triangle(n-1)); } Trace the output of the following program int triangle (int n) { System.out.println (Entering: n= + n); if(n == 1) { System.out.println (Returning 1); return 1; } else { int temp = n + triangle(n-1); System.out.println(Returning + temp); return temp } } Whats really happening? Each time the triangle( ) method calls itself, its argument, which starts at 4, is reduced by 1. The method plunges down into itself again again until its argument is reduced to 1. Then it returns. This triggers an entire series of returns. The method rises back up, phoenix-like, out of the discarded versions of itself. Each time it returns it adds the value of n it was called with to the return value from the method it called. Note: Just before the innermost version returns a 1, there are actually 4 different incarnations of triangle( ) in existence at the same time. Characteristics of recursive methods It calls itself When it calls itself, it does so to solve a smaller problem Theres some version of the problem that is simple enough that the routine can solve it, and return, without calling itself. int triangle (int n) { if(n == 1) // base case return 1; else return (n + triangle(n-1)); } Is recursion efficient? Method calling involves some overhead Control must be transferred to and fro, with each call having its own set of arguments utilising a stack so that the method can access the argument values and know where to return Memory usage may cause stack overflow Recursive computer programs require more memory and computation compared with iterative algorithms, but they are simpler and for many cases a natural way of thinking about the problem. Recursion is usually used because it simplifies a problem conceptually, not because its inherently more efficient Factorials Similar to triangular number, except that: multiplication is the arithmetic operator, not addition factorial(0) = 1, factorial(1) = 1*1 = 1, factorial(2) = 1*2 = 2, factorial(3) = 3*2 = 6 and so on
Factorials int factorial (int n) { if(n == 0) // base case return 1; else return (n * factorial(n-1)); } Find the n-th even number Procedural Method
Algorithm -> Even(positive integer k) Input: k, a positive integer Output: k-th even natural number (the first even being 0)
Algorithm: int i, even; i := 1; even := 0; while( i <k ) { even := even + 2; i := i + 1; } return even . Recursive Algorithm Procedural Binary Search public int find(double searchKey) { int lowerBound = 0; int upperBound = nElems-1; int curIn;
while(true) { curIn = (lowerBound + upperBound ) / 2; if(a[curIn]==searchKey) return curIn; // found it else if(lowerBound > upperBound) return nElems; // can't find it else // divide range { if(a[curIn] < searchKey) lowerBound = curIn + 1; // it's in upper half else upperBound = curIn - 1; // it's in lower half } // end else divide range } // end while } // end find() Recursive Binary Search public int find(double searchKey) { return recFind(searchKey, 0, nElems-1); } //----------------------------------------------------------- private int recFind(double searchKey, int lowerBound, int upperBound) { int curIn;
curIn = (lowerBound + upperBound ) / 2; if(a[curIn]==searchKey) return curIn; // found it else if(lowerBound > upperBound) return nElems; // can't find it else // divide range { if(a[curIn] < searchKey) // it's in upper half return recFind(searchKey, curIn+1, upperBound); else // it's in lower half return recFind(searchKey, lowerBound, curIn-1); } // end else divide range } // end recFind() Partition Algorithm Partition Algorithm public int partitionIt(int left, int right, double pivot) { int leftPtr = left - 1; // right of first elem int rightPtr = right + 1; // left of pivot while(true) { while(leftPtr < right && // find bigger item theArray[++leftPtr] < pivot) ; // (nop)
while(rightPtr > left && // find smaller item theArray[--rightPtr] > pivot) ; // (nop) if(leftPtr >= rightPtr) // if pointers cross, break; // partition done else // not crossed, so swap(leftPtr, rightPtr); // swap elements } // end while(true) return leftPtr; // return partition } // end partitionIt()