270 likes | 426 Views
Recursion. Dr. Bernard Chen Ph.D. University of Central Arkansas. Mathemetical Induction. To prove. Let p ( n ) denote the statement involving the integer variable n . The Principle of Mathematical Induction states:
E N D
Recursion Dr. Bernard Chen Ph.D. University of Central Arkansas
Mathemetical Induction To prove • Let p(n) denote the statement involving the integer variable n. The Principle of Mathematical Induction states: If p(1) is true and, for some integer K >=1 , p(k+1) is true whenever p(k) is true then p(n) is true for all n>=1 . • 4 steps in using Induction: • Base cases; --- p(1), p(2), … • Induction hypothesis (IH); --- assume p(k) is true • Statement to be proved in induction; --- it is true for p(k+1) • Induction step. --- prove p(k+1) is true based on IH
Recursive Function Call • a recursion function is a function that either directly or indirectly makes a call to itself. • but we need to avoid making an infinite sequence of function calls (infinite recursion)
Finding a Recursive Solution • a recursive solution to a problem must be written carefully • the idea is for each successive recursive call to bring you one step closer to a situation in which the problem can easily be solved • this easily solved situation is called the base case • each recursive algorithm must have at least one base case, as well as a general (recursive) case
General format forMany Recursive Functions if (some easily-solved condition) // base case solution statement else// general case recursive function call
A recursive definition int s (int n) { if (n ==1) return 1; else return s(n-1) + n; } A few of problems: • n 0 at the beginning; • return value might be too large to fit in an int.
When a function is called... • a transfer of control occurs from the calling block to the code of the function--it is necessary that there be a return to the correct place in the calling block after the function code is executed; this correct place is called the return address • when any function is called, the run-time stack is used--on this stack is placed an activation record for the function call
Stack Activation Frames • the activation record contains the return address for this function call, and also the parameters, and local variables, and space for the function’s return value, if non-void • the activation record for a particular function call is popped off the run-time stack when the final closing brace in the function code is reached, or when a return statement is reached in the function code • at this time the function’s return value, if non-void, is brought back to the calling block return address for use there
A recursive function int Func ( /* in */ int a, /* in */ int b ) { int result; if ( b == 0 ) // base case result = 0; else if ( b > 0 ) // first general case result = a + Func ( a , b - 1 ) ) ; // instruction 50 return result; }
Run-Time Stack Activation Recordsx = Func(5, 2);// original call at instruction 100 FCTVAL ? result ? b 2 a 5 Return Address 100 original call at instruction 100 pushes on this record for Func(5,2)
record for Func(5,2) Run-Time Stack Activation Recordsx = Func(5, 2);// original call at instruction 100 FCTVAL ? result ? b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 call in Func(5,2) code at instruction 50 pushes on this record for Func(5,1)
record for Func(5,1) record for Func(5,2) Run-Time Stack Activation Recordsx = Func(5, 2);// original call at instruction 100 call in Func(5,1) code at instruction 50 pushes on this record for Func(5,0) FCTVAL ? result ? b 0 a 5 Return Address 50 FCTVAL ? result 5+Func(5,0) = ? b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100
Run-Time Stack Activation Recordsx = Func(5, 2);// original call at instruction 100 FCTVAL 0 result 0 b 0 a 5 Return Address 50 FCTVAL ? result 5+Func(5,0) = ? b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 record for Func(5,0) is popped first with its FCTVAL record for Func(5,1) record for Func(5,2)
Run-Time Stack Activation Recordsx = Func(5, 2);// original call at instruction 100 FCTVAL 5 result 5+Func(5,0) = 5+ 0 b 1 a 5 Return Address 50 FCTVAL ? result 5+Func(5,1) = ? b 2 a 5 Return Address 100 record for Func(5,1) is popped next with its FCTVAL record for Func(5,2)
Run-Time Stack Activation Recordsx = Func(5, 2);// original call at instruction 100 FCTVAL 10 result 5+Func(5,1) = 5+5 b 2 a 5 Return Address 100 record for Func(5,2) is popped last with its FCTVAL
Too much recursion Can Be Dangerous Fibonacci numbers. Long fib (int n) { If (n <=1) return n; Else return fib(n-1) + fib(n-2); }
Too much Recursion Can be Dangerous • This definition will lead to exponential running time. • Reason: -- too much redundant work • Not necessary to use recursive • Write a non-recursive Fibonacci code
Tree • Tree is a fundamental structure in computer science. • Recursive definition: A tree is a root and zero or more nonempty subtrees. • Nonrecursive definition: A tree consists of s set of nodes and a set of directed edges that connect pairs of nodes. That is, a connected graph without loop.
V L R Traversal • Three standard traversal order • preorder - V L R • inorder - L V R • postorder - L R V Inorder: traverse all nodes in the LEFT subtree first, then the node itself, then all nodes in the RIGHT subtree. Preorder: traverse the node itself first, then all nodes in the LEFT subtree , then all nodes in the RIGHT subtree. Postorder: traverse all nodes in the LEFT subtree first, then all nodes in the RIGHT subtree, then the node itself,
1 2 3 4 5 6 Recursive Traversal Implementation Void PrintPreorder (root) if root != null print(root->data); PrintPreorder(root->left); PrintPreorder(root->right); endif; preorder : 1 2 4 5 3 6 inorder : 4 2 5 1 3 6 postorder : 4 5 2 6 3 1 Void PrintInorder (root) if root != null PrintInorder(root->left); print(root->data); PrintInorder(root->right); endif; Void PrintPostorder (root) if root != null PrintPostorder(root->left); PrintPostorder(root->right); print(root->data); endif; The difference is the order of the three statements in the ‘IF’.
Binary Search 3-ways comparisons int binarySearch(vector<int> a[], int x){ int low = 0; int high = a.size() – 1; int mid; while(low <= high) { mid = (low + high) / 2; if(a[mid] < x) low = mid + 1; else if( a[mid] > x) high = mid - 1; else return mid; } return NOT_FOUND; // NOT_FOUND = -1 }//binary search using three-ways comparisons
Some more examples: • Factorials • Binary Search template <class Comparable> int binarySearch( const vector<Comparable> & a, const Comparable & x, int low, int high ) { if( low > high ) return NOT_FOUND; int mid = ( low + high ) / 2; if( a[ mid ] < x ) return binarySearch( a, x, mid + 1, high ); else if( x < a[ mid ] ) return binarySearch( a, x, low, mid - 1 ); else return mid; }
Divide and Conquer • Given an instance of the problem to be solved, split this into several, smaller, sub-instances (of the same problem) independently solve each of the sub-instances and then combine the sub-instance solutions so as to yield a solution for the original instance.
Recursion or Iteration? CLARITY EFFICIENCY