250 likes | 476 Views
Recursion and Recurrence Equations. The execution of a recursive program Deriving recurrence equations. Recursion. What is the recursive definition of n ! ? Translating to Java/c int fact(int n) { if (n<=1) return 1;
E N D
Recursion and Recurrence Equations The execution of a recursive program Deriving recurrence equations
Recursion • What is the recursive definition of n! ? • Translating to Java/c int fact(int n) { if (n<=1) return 1; // Note '*' is done after returning from fact(n-1)else return n*fact(n-1); } Cutler/Head
Recursive algorithms • A recursive algorithm typically contains recursive calls to the same algorithm • In order for the recursive algorithm to terminate, it must contain code for solving directly some “base case(s)” • A direct solution does not include recursive calls. • We use the following notation: • DirectSolutionSize is the “size” of the base case • DirectSolutionCount is the count of the number of operations done by the “direct solution” Cutler/Head
The Run Time Environment The following 2 slides show the program stack after the third call from fact(3) When a function is called an activation records('ar') is created and pushed on the program stack. The activation record stores copies of local variables, pointers to other ‘ar’ in the stack and the return address. When a function returns the stack is popped. A Call Tree for fact(3) returns 6 fact(3) 6 * fact(2) 3 2 * 2 fact(1) 1 1 • int fact(int n) { • if (n<=1) return 1;else return n*fact(n-1); • } Cutler/Head
free memory N =2 function value [=2] AR(fact 2) return address static link = ep0 dynamic link = EP EP N =3 function value [=?] AR(fact 3) return address static link = ep0 dynamic link = ep1 ep1 Val AR(Driver) fact: <ipF,ep0> ep0 Program stack Snapshot of the environment at end of second call to fact AR=Activation Record ep= environmental pointer free memory N =1 function value [=1] AR(fact 1) return address static link = ep0 dynamic link = EP EP N =2 function value [=?] AR(fact 2) return address static link = ep0 dynamic link =ep2 ep2 N =3 function value [=?] AR(fact 3) return address static link = ep0 dynamic link =ep1 ep1 Val AR(Driver) fact: <ipF,ep0> ep0 Program stack Snapshot of the environment at end of third call to fact Cutler/Head
free memory N =3 function value [=6] AR(fact 3) return address free memory static link = ep0 dynamic link = EP EP Val AR(Driver) fact: <ipF,ep0> EP Val AR(Driver) fact: <ipF,ep0> ep0 Program stack Program stack Snapshot of the environment after fact l returns Snapshot of the environment at end of first call to fact Cutler/Head
Goal: Analyzing recursive algorithms • Until now we have only analyzed (derived a count) for non-recursive algorithms. • In order to analyze recursive algorithms we must learn to: • Derive the recurrence equation from the code • Solve recurrence equations. Cutler/Head
Deriving a Recurrence Equation fora Recursive Algorithm • Our goal is to compute the count (Time) T(n) as a function of n, where n is the size of the problem • We will first write a recurrence equation for T(n) For example T(n)=T(n-1)+1 and T(1)=0 • Then we will solve the recurrence equation When we solve the recurrence equation above we will find that T(n)=n, and any such recursive algorithm is linear in n. Solving: Next lecture Cutler/Head
Deriving a Recurrence Equation for a Recursive Algorithm 1. Determine the “size of the problem”. The count T is a function of this size 2. Determine DirectSolSize, such that for sizeDirectSolSize the algorithm computes a direct solution, and the DirectSolCount(s). Cutler/Head
Deriving a Recurrence Equation for a Recursive Algorithm To determine GeneralCount: 3. Identify all the recursive calls done by a single call of the algorithm and their counts, T(n1),…,T(nk) and compute RecursiveCallSum = 4. Determine the “non recursive count” t(size) done by a single call of the algorithm, i.e., the amount of work, excluding the recursive calls done by the algorithm Cutler/Head
Deriving DirectSolutionCount for Factorial int fact(int n) { if (n<=1) return 1; // Note '*' is done after returning from fact(n-1)else return n*fact(n-1); 1. Size = n 2.DirectSolSize is (n<=1) 3. DirectSolCount is (1) The algorithm does a small constant number of operations (comparingn to 1, and returning) Cutler/Head
Deriving a GeneralCount for Factorial int fact(int n) { if (n<=1) return 1; // Note '*' is done after returning from fact(n-1)else return n * fact(n-1); 3. RecursiveCallSum = T( n - 1) 4. t(n) = (1) (for if, *, -, return) Operations counted in t(n) The only recursive call, requiring T(n - 1) operations Cutler/Head
Deriving a Recurrence Equation for Mystery In this example we are not concerned with what mystery computes. Our goal is to simply write the recurrence equation mystery (n) 1. ifn£ 1 2. then returnn 3. else return (5 * mystery(n -1) - 6* mystery(n -2) ) Cutler/Head
Deriving a DirectSolutionCount for Mystery 1. Size = n 2. DirectSolSize is (n<=1) 3. DirectSolCount is (1) The algorithm does a small constant number of operations (comparingn to 1, and returning) Cutler/Head
Deriving a GeneralCount for Mystery A recursive call to Mystery requiring T(n - 1) mystery (n) 1. ifn£ 1 2. then returnn 3. else return (5 * mystery(n -1) - 6 * mystery(n - 2) ) A recursive call to Mystery requiring T(n - 2) Operations counted in t(n) Cutler/Head
Deriving a Recurrence Equation for Mystery 3. RecursiveCallSum = T(n-1) + T(n-2) 4. t (n)= (1) The non recursive count includes the comparison n<=1, the 2 multiplications, the subtraction, and the return. So (1). Cutler/Head
Deriving a Recurrence Equation for Multiply Barometer operation Multiply(y, z)//binary multiplication 1. if (z ==0) return 0 2. elseifz is odd 3. thenreturn (multiply(2y,ëz/2û) + y) 4. else return (multiply(2y,ëz/2û)) To derive the recurrence equation we need to determine the size of the problem. The variable which is decreased and provides the direct solution is z. So we can use z as the size. Another possibility is to use n which is the number of bits in z (n=ëlg zû+1). Let addition be our barometer operation. We do 0 additions for the direct solution. So DirectSolutionSize =0, and DirectSolutionCount=0 Cutler/Head
Deriving a Recurrence Equation for Multiply 1. RecursiveCallSum = T(z/2) t(z) = 1 addition in the worst case. So Solving this equation we get T(z)= (lg z)= (n). 2. RecursiveCallSum = T(n-1) since z/2 has n-1 bits Solving this equation we get T(n)= (n) Cutler/Head
Deriving a recurrence equation for minimum Minimum(A,lt,rt) // minimum(A,1,length(A)) 1. if rt - lt£ 1 2. then return (min(A[lt], A[rt])) 3. elsem1 = minimum(A,lt,ë(lt+rt)/2û ) 4. m2 = minimum(A,ë(lt+rt)/2û +1,rt) 5. return (min (m1, m2)) • This procedure computes the minimum of the left half of the array, the right half of the array, and the minimum of the two. • Size = rt-lt+1= n • DirectSolutionSize is n = (rt - lt)+1 £ 1+1=2. • DirectSolutionCount = (1) Cutler/Head
Deriving a recurrence equation for minimum Minimum(A,lt,rt) // minimum(A,1,length(A)) 1. if rt - lt£ 1 2. then return (min(A[lt], A[rt])) 3. elsem1 = minimum(A,lt,ë(lt+rt)/2û ) 4. m2 = minimum(A,ë(lt+rt)/2û +1,rt) 5. return (min (m1, m2)) Two recursive calls with n/2 elements. So T(n/2) + T(n/2) Cutler/Head
Deriving a recurrence equation for Merge Sort: 1 if (n 2) 2 moveFirst(S, S1, (n+1)/2)) // divide3 moveSecond(S, S2, n/2) // divide4 Sort(S1) // recurs5 Sort(S2) // recurs6 Merge( S1, S2, S) // conquers DirectSolutionSize is n<2 DirectSolutionCount is (1) RecursiveCallSum is T( n/2) + T( n/2) The non recursive count t(n) = (n) Cutler/Head
Recurrence Equation for cost. • The implementation of the moves costs Q(n) and the merge costs Q(n). So the total cost for dividing and merging is Q(n). • The recurrence relation for the run time of Sort is T(n) = T( n/2) + T( n/2) + Q(n) . T(0) =T(1) = Q(1) • The solution is T(n)= Q(nlg n) Cutler/Head
Computing xn • We can decrease the number of times that x is multiplied by itself by observing that to compute x8 we need only 3 multiplications (x2=x*x, x4=x2*x2, and x8=x4*x4) and when we want of compute x9, we need 4 multiplications (x2=x*x, x4=x2*x2, x8=x4*x4 andx9= x8*x) • A recursive procedure for computing xn should be (lg n) • For the following algorithm we will derive the worst case recurrence equation. • Note: we are ignoring the fact that the numbers will quickly become too large to store in a long integer Cutler/Head
Recursion - Power long power (long x, long n) { if (n == 0) { return 1; } else { long p = power(x, n/2); if ((n % 2) == 0) { return p*p; } else { return x * p*p;} } } We use the * as our barometer operation. Cutler/Head
Deriving a Recurrence Equation for Power Size = n DirectSolutionSize is n=0; DirectSolutionCount is 0; RecursiveCallSum is T(n/2) t(n) = 2 multiplications in the worst case T(n)=0 for n=0 T(n)=T(n/2)+2 for n>0 // Cutler/Head