Recursion: Data Structure With C
Recursion: Data Structure With C
Recursion
Topic:
In this chapter we are departing recursion concepts through the following steps as
millstones.
Presentation starts with recursion definition, how recursion works ?, designing of
recursive algorithm with appropriate methodology, limitation of recursion and to end
with summarizing the overall concepts.
There are mainly two approaches for repetitive approach.
Iteration
Recursion
Recursion is a repetitive process in which an algorithm calls itself. by and large
recursion is organized in such a way that a function or subroutine calls itself. The
following Figure 1 and Figure 2 portrayed the typical pictorial examples for recursive
calling.
Base case(s): Values of the input variables for which we perform no recursive calls are
called base cases (there should be at least one base case). Every possible chain of
recursive calls must eventually reach a base case.
Recursive calls.
This is calls to the current method. Each recursive call should be defined so that it
makes progress towards a base case. The recursive solution for the given problem
involves in a two-way journey, firstly we decompose the problem from the top to the
bottom and then we solve the problem from the bottom to the top.
How Recursive Works ?
In a recursive function execution process each call sets up a new instance of all the
parameters and the local variables. As always, when the method completes, control
returns to the method that invoked it (which might be another invocation of the same
method)
Example : pow(4, 3) = 4 * pow(4, 2)
= 4 * 4 * pow(4, 1)
= 4 * 4 * 4 * pow(4, 0)
=4*4*4*1
= 64
How recursion works at run time?
It is quite interesting and need to understand what happens when a function is
called.. Whenever a function is called, a block of memory is allocated to it in a run-time,
such kind of structure is called the stack.
This block of memory will contain the following information. a) the functions local
variables, b)local copies of the functions call-by-value parameters, c)pointers to its callby-reference parameters, and d) a return address, in other words where in the program
the function was called from. When the function finishes, the program will continue to
execute from that point.
Activation Record
Complier will be automatically create the activation record for every function call. For
example memory for such record in Java complier allocates to store information about
each running method. Such as return address ("RA") argument values, local variable
values. Java stacks up the records as methods are called. A method'
s activation record
exists until it returns. This records helps us trace the behavior of a recursive method, in
figure 3 depicts the activation record.
x =[4]
y = [ 0 ] | pow(4, 0)
| RA = [pow(4,1)]
|
|x =[4]
y = [ 1 ] | pow(4, 1)
| RA = [pow(4,2)]
|
|x =[4]
y = [ 2 ] | pow(4, 2)
| RA = [pow(4,3)]
|
|x =[4]
y = [ 3 ] | pow(4, 3)
| RA = [main]
|
|
| main
Figure 3: activation record
Recursion
A function that is defined in terms of itself is called self-referential, or recursive.
Recursive functions are designed in 3 steps
Step 1. Identify a base base case an instance of problem whose solution is trivial
Ex: The factorial function has two base cases:
if n = 0 : n! = 1
if n = 1 : n! = 1
Step 2. Identify an induction step: a means of solving non trivial instance of problem
using one or more smaller instances of problem
Ex: In the factorial problem, we solve the big problem using a smaller version of the
problem, n! = (n-1)! n
Step 3: Form an algorithm from the base and induction step
In figure 4 and 5 elaborates the recursive function call for factorial computation.
Algorithm to compute factorial
Factorial (N)
1.
Receive N
2.
if N > 1 return
Factorial(N-1) * N
else
return 1
Indirect Recursion
A method invoking itself is considered to be direct recursion. A method could invoke
another method, which invokes another, etc., until eventually the original method is
invoked again Ex: method m1 could invoke m2, which invokes m3, which in turn
invokes m1 again and it is illustrated in figure 6.
if n =0
1
if n =1
Fibonacci ( n 1) + Fibonacci ( n 2 ) otherwise
Analysis
The efficiency of the Fibonacci recursive algorithm is exponential behaviour which is
explored using figure 11
Algorithm
Recursive Algorithm_1
Fun1(x)
If (x<5) return(3*x)
Else
return(2*Fun1(x-5)+7)
Exercises:
a) Fun1(4) ?
= 3*4= 12
b) Fun1(10)?
= (2 * Fun1(5) +7) = (2*(2*fun1(0)+7)+7) = (2*(2*(3*0)+7)+7) = 21
c) Fun1(12) ?
=(2*Fun1(7)+7) =(2*(2*Fun1(2)+7)+7) =(2*(2*(3*2)+7)+7) = 45
Recursive Algorithm_2
Fun2(x,y)
If (x<y) return -3
Else
return(Fun2(x-y, y+3)+y)
Exercises:
a) Fun1(2,7) ?
= -3
b) Fun2(5,3)?
= Fun2(2,6) +3 = -3 + 3 = 0
c) Fun2(15,3) ?
=Fun2(12,6)+3 =(Fun2(6,9)+3) +3
=( -3 + 3 ) + 3
=3
Newtons Method
SquareRoot( num, ans, tol)
If |ans2-num| < tol return ans
else
return(SquareRoot(num,(ans2+num)/(2*ans), tol)
Exercises:
a) Squareroot(9,3,0.01) ?
=3
b) SquareRoot(4,4,0.01)?
=(SquareRoot(4,(16+4)/(2*4),0.01) = 4,2,0.01 = 2
Sel_algo(n,k)
C(n,k)
If (k==0 or n==k) return 1
else
return(C(n-1,k)+C(n-1,k-1)
Exercises:
C(5,4) ?
= c(4,4)+c(4,3)
= 1+c(3,3)+c(3,2)
= 1+1+c(2,2)+c(2,1)
= 1+1+1+c(1,1)+c(1,0)
=5
In several state lotteries players chose six number out of a series of possible numbers,
Calculate the number of possible combinations C(49,6)=13,983,816 different
combinations of 6 numbers.
Ackerman Formula
Ack(M,N)
If (M==0) return(N+1)
=Ack(0,Ack(0,Ack(0,6)))
=Ack(0,Ack(0,7))
=Ack(0,8)
=9
More Exercises Problems
b) Ack(2,5) =13
c) Ack(0,3) =4
d) Ack(3,0) =5
Limitations of Recursion
Recursion should not be used if the answer to any of the following questions is no:
Is the algorithm or data structure naturally suited to recursion (tree is the first choice) ?
Is the recursive solution shorter and more understandable?.
Does the recursive solution run within acceptable time and space limits ?
As a general rule, recursive algorithms should be effectively used only when their
efficiency is logarithmic.
Summary
The trick with recursion is to ensure that each recursive call gets closer to a base case. In
most of the examples, We have looked at, the base case is the empty list, and the list gets
shorter with each successive call. Recursion can always be used instead of a loop. (This
is a mathematical fact.) In declarative programming languages, like Prolog, there are no
loops. There is only recursion. Recursion is elegant and sometimes very handy, but it is
marginally less efficient than a loop, because of the overhead associated
with
maintaining the stack.