rahulsingla.com - Programming Techniques
http://www.rahulsingla.com/category/articles/programming-techniques
enRecursion
http://www.rahulsingla.com/blog/2009/10/recursion
<!-- google_ad_section_start --><div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:blogPost content:encoded"><p id="__mce">Before giving any formal definition of Recursion, I will like to discuss a scenario...<br /><br /> Browing your files on local disk is a very common task. Let us assume you have to write a procedure that performs an action (like calculating the size) on every file on your C:<br /> The algorithm will be something like follows:<br /><br /> Apply the action on all files in the root directory. Then pick up its sub-diectory &amp; apply the action on all its files. Then pick up the sub-sub directory & continue the procedure until there's no more nested sub-directories.<br /> The next step is to backtrack to the parent directory & perform the entire action again on another sub-directory... ( I hope u understand what's going on) <br /> The entire procedure goes on until all of the files have been processed.<br /><br /> This is the ideal scenario where Recursion can kick in.<br /><br /> The entire concept of recursion is as simple as this:<br /><span style="color: red;">Recursion can be applied to any problem that can be divided into sub-problems that are similar in nature to the original problem.</span><br /><br /> Coming back to the above problem, the original problem was to <span style="color: red;">Browse</span> the root directory.<br /> It could be divided into sub-problems as performing the action on root directory files plus <span style="color: red;">Browsing</span> the sub-directory files...<br /><br /> This is Recursion.<br /><br /> Let's take another scenario. Lets assume you have to calculate the factorial of a number (say 5).<br /> The technical definition of a factorial is (remember factorials apply only to integers >=0):<br /> fact(n) = n*fact(n-1); n>0<br /> = 1 ; n=0<br /><br /> This again is a recursive definition. The original problem is divided into sub-problem (n*fact(n-1)) that is exactly similar to the original problem....<br /><br /> That's Recursion in its simplest terms...</p><p> </p><p><span style="color: rgb(0, 90, 140);"><span style="font-size: medium;">Recursive Conditions</span></span></p><p>The last example of Recursion brought us to some very important conclusions. To implement any recursive definition, it should satisfy some conditions.<br /><br /> In a nut-shell, any such definition should invariably satisfy the following three conditions:<br /><br /> 1. A recursive function should contain a call to itself (thus, the task should be divisible into sub-tasks, similar in nature to the original one).<br /> 2. There must be a condition which at some point of time becomes true, after which no further recursive calls are made.<br /> 3. Every recursive call should take us a step closer to satisfying that condition.<br /><br /> In the case of factorial definition, the three conditions are satisfied as follws:<br /> 1. Calculating factorial of a number first requires calculating factorial of a number smaller than it.<br /> 2. The condition for no further recursive calls is<br /> fact(n) = 1; n=0<br /><br /> So 5! = 5 * 4!<br /> = 5 * 4 * 3!<br /> = 5 * 4 * 3 * 2!<br /> = 5 * 4 * 3 * 2 * 1!<br /> = 5 * 4 * 3 * 2 * 1 * 0!<br /> = 5 * 4 * 3 * 2 * 1 * 1<br /><br /><span style="color: red;">Notice</span> that in the last step, when n=0, instead of making further calls to itself, the procedure ends returning a value & making no further calls.<br /><br /> 3. The third condition is obvious, after every call, the number is decremented... which ultimately takes us to the condition when n becomes 0 (satisfying it so that no further calls are made).<br /><br /> The third point above also gives an idea, why factorials of negative numbers don't exist. They can be decremented to infinity in each step, & so the condition of n becoming 0 will never be satisfied.</p><p> </p><p><span style="color: rgb(0, 90, 140);"><span style="font-size: medium;">Detailed Example</span></span></p><p>Now, lets move from the theoretical to the practical aspects of Recursion.<br /><br /> Lets define a recursive function fact() to calculate factorial of a given positive number.<br /> The function would be as follows:<br /><br /></p><p>{syntaxhighlighter brush: cpp;fontsize: 100; first-line: 1; }int fact(int n)
{
if (n==0)
return(1);
else
return(n*fact(n-1));
}{/syntaxhighlighter}</p><p><br /> The above function implements the already discussed recursive definition of factorial.</p><p>This brings us to another aspect. You may ask, why should I use Recursion when the same task could be performed with a simple loop...<br /><br /></p><p></p><pre class="brush: cpp;fontsize: 100; first-line: 1; ">fact=1;
for(i=0;i&lt;n;i++)
fact=fact*i;</pre><p><br /> Agreed....<br /> In theory, every problem that is defined recursively can be implemented using loops.<br /> This means that there is always a work around to Recursion.<br /><br /> But there are situations where a recursive procedure makes more sense, and is easy to implement.<br /> I will gve two examples to support this statement:<br /><br /> 1. First consider the above problem of <span style="color: red;">Browing</span> the directory structure.<br /> Its not hard to imagine the complexity had the problem been solved with loops.<br /> Implementing it with recursion is as easy as follows:<br /><br /> (The listing is given in VB for understanding purposes as collections in VB make Browing folders easier. Anyone having a problem with this code can request a c equivalent of the same)<br /><br /><br /></p><p> </p><p></p><pre class="brush: vb;fontsize: 100; first-line: 1; ">Sub scanfolder(thisFolder as Folder)
Dim allFolders as Folders
Set allFolders=thisFolder.SubFolders 'Extract all sub folders
For Each Folder in allFolders
' Apply the process here
scanfolder(thisFolder.path)
Next
End Sub</pre><p> 2. We all have studied 'Trees'. These data structures play a very crucial role in any data management.<br /> I assume u all have studied the 'Tree Traversal' algorithms. (If u dont, u can ask me to reproduce them here).<br /> If u recall, they are implemented via stack if we dont use recursion &amp; are quite complex at the first instance (especially the Post-Order traversal).<br /><br /> So, here's the Recursive implementation of Post-Order tree traversal in C.<br /><br /></p><p>{syntaxhighlighter brush: cpp;fontsize: 100; first-line: 1; }void PostOrder (Node xx)
{
if (xx = NULL)
return;
if (xx->left != NULL)
PostOrder(xx->left);
if (xx->right !=NULL)
PostOrder(xx->right);
'Apply Process u want to node xx here
}{/syntaxhighlighter}</p><p> </p><p><span style="color: rgb(0, 90, 140);"><span style="font-size: medium;">Recursion - Finer Points</span></span></p><p>And now, I will discuss some finer points about Recursion.<br /><br /> First, a recursive definition is always less efficient than when the same procedure is implemented with loops. This is because the overhead related with the function calling itself again &amp; again.<br /><br /> Second, it's very easy to goof-up recursive implementations. That's primarily because one of the above three points a recursive definition should satify are violated.<br /> The second &amp; third points are very important in this context.<br /> Remember to include a condition that terminates further recursive calls. Also see, that each recursive call takes a step further to satisfy that condition.<br /> Violating any of these would result in any infinite loop, ultimately causing a stack overflow (i believe everyone of us has encountered this error, when developing our first recursive procedure ).</p><p>Just for a quick recall, I would reiterate how the above function satisfied all the three conditions for Recursion...<br /><br /> 1. Clearly, it calls itself in its body... So its recursive.<br /> 2. The condition to terminate further calls is:<br /> 'When no more sub-folders of current folder exist, dont make further calls & return'.<br /> As u can see, this statement is implemented via the for loop in the above code.<br /><br /> 3. All of us know, that folders do not have sub-folders endlessly. At some point, a folder will have no further sub-folder. So, in each step, we are coming close to that situation. This is where there will be no further calls....</p><p> </p><p><span style="color: rgb(0, 90, 140);"><span style="font-size: medium;">Closing Remarks</span></span></p><p>Some final points from my side...<br /><br /> The above example underlines an advantage of Recursion. Suppose u had to implement it via loop without Recursion.<br /><br /> The major problem u would have had was to handle the allFolders collection.<br /> In principle, u would have two problems.<br /><br /> 1. You never not know how many levels of nesting folders, a client's computer have. So, u would have problem deciding how many times to run the loop, &amp; also how to keep the track of nesting. This would leave u no choice, but dynamic memory management for the allFolders collection, which we all know can get quite messy.<br /><br /> With Recursion, this is not a problem, as u dont have to decide either loop count or the level of nesting. Everytime a new recursive call is made, a new collection alFolders is created. So a new data structure is created on every call & there's no need of dynamic memory management.<br /><br /> This point would be further clear, if u consider the example of tree traversal presented earlier.<br /> Without recursion, u would have to use a stack, which had to be resized dynamically.<br /> With Recursion, there's no such thing (Internally, all recursive calls occur on memory stack u know!!!)<br /><br /> 2. You would have problem in backtracking. With Recrsion, backtracking occurs automatically.<br /><br /><br /> I am making a couple of further points, u can safely ignore if u r not that well accustomed to Recursion.<br /> You may ask, how do i pass information between successive recursive calls.<br /> Simple, either use parametres...<br /> or for another approach, u can declare Static variables in the function &amp; manipulate it accordingly to pas* information back &amp; forth between the recursive calls...<br /><br /> As i discussed, every recursive definition can be implemented non-recursively.<br /> Remember, u would always have to use a stack anytime u do so...</p></div></div></div><!-- google_ad_section_end --><div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Articles: </div><div class="field-items"><div class="field-item even" rel="schema:category"><a href="/category/articles/programming-techniques" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Programming Techniques</a></div></div></div><span property="schema:name" content="Recursion" class="rdf-meta element-hidden"></span><span rel="schema:url" resource="/blog/2009/10/recursion" class="rdf-meta element-hidden"></span><ul class="links inline"><li class="addtoany first last"><span><span class="a2a_kit a2a_target addtoany_list" id="da2a_1">
<a class="a2a_dd addtoany_share_save" href="https://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.rahulsingla.com%2Fblog%2F2009%2F10%2Frecursion&title=Recursion"><img src="/sites/all/modules/addtoany/images/share_save_171_16.png" width="171" height="16" alt="Share this"/></a>
</span>
<script type="text/javascript">
<!--//--><![CDATA[//><!--
da2a.script_load();
//--><!]]>
</script></span></li>
</ul>Sat, 10 Oct 2009 11:38:22 +0000rahul4 at http://www.rahulsingla.comhttp://www.rahulsingla.com/blog/2009/10/recursion#comments