Chapter 26: R Function Recursion
Part 1: What is Recursion?
Recursion is a programming technique where a function calls itself to solve a problem by breaking it down into smaller instances of the same problem.
The Two Essential Parts of Every Recursive Function
Every recursive function must have:
-
Base Case: A condition that stops the recursion (the smallest doll)
-
Recursive Case: The function calling itself with a smaller version of the problem
The Basic Structure
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
recursive_function <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>parameter<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Base case - when to stop</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>base_case_condition<span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>simple_value<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Recursive case - call yourself with modified parameters</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment"># Do something</span> result <span class="token operator"><-</span> recursive_function<span class="token punctuation">(</span>modified_parameter<span class="token punctuation">)</span> <span class="token comment"># Combine with current computation</span> return<span class="token punctuation">(</span>final_result<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Part 2: Classic Examples of Recursion
Example 1: Factorial – The “Hello World” of Recursion
The factorial of n (written as n!) is the product of all positive integers less than or equal to n:
-
5! = 5 × 4 × 3 × 2 × 1 = 120
-
3! = 3 × 2 × 1 = 6
-
1! = 1
-
0! = 1 (by definition)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<span class="token comment"># Recursive factorial function</span> factorial_recursive <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Base case: if n is 0 or 1, return 1</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Base case reached with n ="</span><span class="token punctuation">,</span> n<span class="token punctuation">)</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Recursive case: n * factorial of (n-1)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Computing"</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> <span class="token string">"* factorial("</span><span class="token punctuation">,</span> n<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">")"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> result <span class="token operator"><-</span> n <span class="token operator">*</span> factorial_recursive<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Returning"</span><span class="token punctuation">,</span> result<span class="token punctuation">,</span> <span class="token string">"for n ="</span><span class="token punctuation">,</span> n<span class="token punctuation">)</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test it</span> print<span class="token punctuation">(</span>factorial_recursive<span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
Output with tracing:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[1] "Computing 5 * factorial( 4 )" [1] "Computing 4 * factorial( 3 )" [1] "Computing 3 * factorial( 2 )" [1] "Computing 2 * factorial( 1 )" [1] "Base case reached with n = 1" [1] "Returning 2 for n = 2" [1] "Returning 6 for n = 3" [1] "Returning 24 for n = 4" [1] "Returning 120 for n = 5" [1] 120 |
Let’s trace through what happens:
-
factorial_recursive(5)calls5 * factorial_recursive(4) -
factorial_recursive(4)calls4 * factorial_recursive(3) -
factorial_recursive(3)calls3 * factorial_recursive(2) -
factorial_recursive(2)calls2 * factorial_recursive(1) -
factorial_recursive(1)hits base case, returns 1 -
Then it unwinds: 2 × 1 = 2, 3 × 2 = 6, 4 × 6 = 24, 5 × 24 = 120
Example 2: Fibonacci Sequence
The Fibonacci sequence starts with 0, 1, and each subsequent number is the sum of the two preceding ones:
0, 1, 1, 2, 3, 5, 8, 13, 21, …
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<span class="token comment"># Recursive Fibonacci (elegant but inefficient)</span> fibonacci <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Base cases</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Recursive case</span> return<span class="token punctuation">(</span>fibonacci<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> fibonacci<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test it</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token keyword">in</span> <span class="token number">0</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"F("</span><span class="token punctuation">,</span> i<span class="token punctuation">,</span> <span class="token string">") ="</span><span class="token punctuation">,</span> fibonacci<span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Output:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
F( 0 ) = 0 F( 1 ) = 1 F( 2 ) = 1 F( 3 ) = 2 F( 4 ) = 3 F( 5 ) = 5 F( 6 ) = 8 F( 7 ) = 13 F( 8 ) = 21 F( 9 ) = 34 F( 10 ) = 55 |
Visualizing the Recursive Calls for Fibonacci
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<span class="token comment"># Fibonacci with tracing to see the recursion tree</span> fib_trace <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">,</span> depth <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> indent <span class="token operator"><-</span> paste<span class="token punctuation">(</span>rep<span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">,</span> depth<span class="token punctuation">)</span><span class="token punctuation">,</span> collapse <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span>indent<span class="token punctuation">,</span> <span class="token string">"fib("</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> <span class="token string">") called\n"</span><span class="token punctuation">,</span> sep <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span>indent<span class="token punctuation">,</span> <span class="token string">"→ returns 0 (base case)\n"</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span>indent<span class="token punctuation">,</span> <span class="token string">"→ returns 1 (base case)\n"</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> cat<span class="token punctuation">(</span>indent<span class="token punctuation">,</span> <span class="token string">" Computing fib("</span><span class="token punctuation">,</span> n<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">") + fib("</span><span class="token punctuation">,</span> n<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">")\n"</span><span class="token punctuation">,</span> sep <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">)</span> a <span class="token operator"><-</span> fib_trace<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">,</span> depth <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> b <span class="token operator"><-</span> fib_trace<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">,</span> depth <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> result <span class="token operator"><-</span> a <span class="token operator">+</span> b cat<span class="token punctuation">(</span>indent<span class="token punctuation">,</span> <span class="token string">"→ returns "</span><span class="token punctuation">,</span> result<span class="token punctuation">,</span> <span class="token string">" ("</span><span class="token punctuation">,</span> a<span class="token punctuation">,</span> <span class="token string">" + "</span><span class="token punctuation">,</span> b<span class="token punctuation">,</span> <span class="token string">")\n"</span><span class="token punctuation">,</span> sep <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Uncomment to see the tree (warning: it's big!)</span> <span class="token comment"># fib_trace(5)</span> |
Part 3: Understanding the Call Stack
Every recursive call adds a new frame to the call stack. When base cases are reached, the stack unwinds.
Visualizing the Stack
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<span class="token comment"># Function to demonstrate the call stack</span> countdown <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Pushing frame for n ="</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> <span class="token string">"onto stack\n"</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Base case reached! Starting to unwind...\n"</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token string">"Blast off!"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> result <span class="token operator"><-</span> countdown<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Popping frame for n ="</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> <span class="token string">"from stack\n"</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Run it</span> countdown<span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> |
Output:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Pushing frame for n = 3 onto stack Pushing frame for n = 2 onto stack Pushing frame for n = 1 onto stack Pushing frame for n = 0 onto stack Base case reached! Starting to unwind... Popping frame for n = 1 from stack Popping frame for n = 2 from stack Popping frame for n = 3 from stack [1] "Blast off!" |
Part 4: More Practical Examples
Example 1: Sum of a Vector (Without Using sum())
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<span class="token comment"># Recursive sum function</span> recursive_sum <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>vec<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Base case: empty vector sums to 0</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>length<span class="token punctuation">(</span>vec<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Base case: single element</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>length<span class="token punctuation">(</span>vec<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Recursive case: first element + sum of rest</span> return<span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">+</span> recursive_sum<span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test</span> numbers <span class="token operator"><-</span> c<span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">30</span><span class="token punctuation">,</span> <span class="token number">40</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Sum:"</span><span class="token punctuation">,</span> recursive_sum<span class="token punctuation">(</span>numbers<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Check:"</span><span class="token punctuation">,</span> sum<span class="token punctuation">(</span>numbers<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
Example 2: Finding Maximum Value in a Vector
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<span class="token comment"># Recursive maximum function</span> recursive_max <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>vec<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Base case: single element</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>length<span class="token punctuation">(</span>vec<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Recursive case: compare first with max of rest</span> max_of_rest <span class="token operator"><-</span> recursive_max<span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">></span> max_of_rest<span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>max_of_rest<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment"># Test</span> numbers <span class="token operator"><-</span> c<span class="token punctuation">(</span><span class="token number">45</span><span class="token punctuation">,</span> <span class="token number">23</span><span class="token punctuation">,</span> <span class="token number">67</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">,</span> <span class="token number">89</span><span class="token punctuation">,</span> <span class="token number">34</span><span class="token punctuation">,</span> <span class="token number">56</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Max:"</span><span class="token punctuation">,</span> recursive_max<span class="token punctuation">(</span>numbers<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Check:"</span><span class="token punctuation">,</span> max<span class="token punctuation">(</span>numbers<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
Example 3: Power Function (x^n)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<span class="token comment"># Recursive power function</span> power_recursive <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Base cases</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Recursive case</span> return<span class="token punctuation">(</span>x <span class="token operator">*</span> power_recursive<span class="token punctuation">(</span>x<span class="token punctuation">,</span> n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># More efficient version using divide and conquer</span> power_fast <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Base cases</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token comment"># Divide and conquer</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token percent-operator operator">%%</span> <span class="token number">2</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># If n is even: x^n = (x^(n/2))^2</span> half <span class="token operator"><-</span> power_fast<span class="token punctuation">(</span>x<span class="token punctuation">,</span> n<span class="token operator">/</span><span class="token number">2</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>half <span class="token operator">*</span> half<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment"># If n is odd: x^n = x * x^(n-1)</span> return<span class="token punctuation">(</span>x <span class="token operator">*</span> power_fast<span class="token punctuation">(</span>x<span class="token punctuation">,</span> n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment"># Compare</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"2^10 ="</span><span class="token punctuation">,</span> power_recursive<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"2^10 ="</span><span class="token punctuation">,</span> power_fast<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Check:"</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token operator">^</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
Example 4: Binary Search
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<span class="token comment"># Recursive binary search (works on sorted vectors)</span> binary_search <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>vec<span class="token punctuation">,</span> target<span class="token punctuation">,</span> left <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> right <span class="token operator">=</span> length<span class="token punctuation">(</span>vec<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Base case: element not found</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>left <span class="token operator">></span> right<span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Find middle index</span> mid <span class="token operator"><-</span> floor<span class="token punctuation">(</span><span class="token punctuation">(</span>left <span class="token operator">+</span> right<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token comment"># Base case: found it</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>vec<span class="token punctuation">[</span>mid<span class="token punctuation">]</span> <span class="token operator">==</span> target<span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>mid<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Recursive cases</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>vec<span class="token punctuation">[</span>mid<span class="token punctuation">]</span> <span class="token operator">></span> target<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Search left half</span> return<span class="token punctuation">(</span>binary_search<span class="token punctuation">(</span>vec<span class="token punctuation">,</span> target<span class="token punctuation">,</span> left<span class="token punctuation">,</span> mid <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment"># Search right half</span> return<span class="token punctuation">(</span>binary_search<span class="token punctuation">(</span>vec<span class="token punctuation">,</span> target<span class="token punctuation">,</span> mid <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> right<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment"># Test</span> sorted_numbers <span class="token operator"><-</span> sort<span class="token punctuation">(</span>sample<span class="token punctuation">(</span><span class="token number">1</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>sorted_numbers<span class="token punctuation">)</span> target <span class="token operator"><-</span> sorted_numbers<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> position <span class="token operator"><-</span> binary_search<span class="token punctuation">(</span>sorted_numbers<span class="token punctuation">,</span> target<span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Found"</span><span class="token punctuation">,</span> target<span class="token punctuation">,</span> <span class="token string">"at position"</span><span class="token punctuation">,</span> position<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Search for non-existent value</span> print<span class="token punctuation">(</span>binary_search<span class="token punctuation">(</span>sorted_numbers<span class="token punctuation">,</span> <span class="token number">999</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
Example 5: Directory Tree Traversal
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<span class="token comment"># Recursive function to list files in a directory tree</span> list_files_recursive <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>path <span class="token operator">=</span> <span class="token string">"."</span><span class="token punctuation">,</span> indent <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Get all items in current directory</span> items <span class="token operator"><-</span> list.files<span class="token punctuation">(</span>path<span class="token punctuation">,</span> full.names <span class="token operator">=</span> <span class="token boolean">TRUE</span><span class="token punctuation">)</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>item <span class="token keyword">in</span> items<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Check if it's a directory</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>file.info<span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token operator">$</span>isdir<span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span>indent<span class="token punctuation">,</span> <span class="token string">"📁 "</span><span class="token punctuation">,</span> basename<span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"/\n"</span><span class="token punctuation">,</span> sep <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">)</span> <span class="token comment"># Recursive call for subdirectory</span> list_files_recursive<span class="token punctuation">(</span>item<span class="token punctuation">,</span> paste0<span class="token punctuation">(</span>indent<span class="token punctuation">,</span> <span class="token string">" "</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment"># It's a file</span> size <span class="token operator"><-</span> file.info<span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token operator">$</span>size cat<span class="token punctuation">(</span>indent<span class="token punctuation">,</span> <span class="token string">"📄 "</span><span class="token punctuation">,</span> basename<span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">" ("</span><span class="token punctuation">,</span> format<span class="token punctuation">(</span>size<span class="token punctuation">,</span> big.mark <span class="token operator">=</span> <span class="token string">","</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">" bytes)\n"</span><span class="token punctuation">,</span> sep <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment"># List current directory (be careful with large directories!)</span> <span class="token comment"># list_files_recursive(".")</span> |
Part 5: Tree Recursion and Data Structures
Example: Binary Tree Traversal
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
<span class="token comment"># Define a simple binary tree structure</span> create_node <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>value<span class="token punctuation">,</span> left <span class="token operator">=</span> <span class="token keyword">NULL</span><span class="token punctuation">,</span> right <span class="token operator">=</span> <span class="token keyword">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>list<span class="token punctuation">(</span> value <span class="token operator">=</span> value<span class="token punctuation">,</span> left <span class="token operator">=</span> left<span class="token punctuation">,</span> right <span class="token operator">=</span> right <span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Create a sample tree</span> <span class="token comment"># 5</span> <span class="token comment"># / \</span> <span class="token comment"># 3 8</span> <span class="token comment"># / \ \</span> <span class="token comment"># 1 4 9</span> tree <span class="token operator"><-</span> create_node<span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> left <span class="token operator">=</span> create_node<span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> left <span class="token operator">=</span> create_node<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> right <span class="token operator">=</span> create_node<span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">,</span> right <span class="token operator">=</span> create_node<span class="token punctuation">(</span><span class="token number">8</span><span class="token punctuation">,</span> right <span class="token operator">=</span> create_node<span class="token punctuation">(</span><span class="token number">9</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token comment"># Recursive in-order traversal (left, root, right)</span> inorder_traversal <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.null<span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token keyword">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Visit left subtree</span> inorder_traversal<span class="token punctuation">(</span>node<span class="token operator">$</span>left<span class="token punctuation">)</span> <span class="token comment"># Visit root</span> cat<span class="token punctuation">(</span>node<span class="token operator">$</span>value<span class="token punctuation">,</span> <span class="token string">" "</span><span class="token punctuation">)</span> <span class="token comment"># Visit right subtree</span> inorder_traversal<span class="token punctuation">(</span>node<span class="token operator">$</span>right<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Recursive pre-order traversal (root, left, right)</span> preorder_traversal <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.null<span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token keyword">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Visit root</span> cat<span class="token punctuation">(</span>node<span class="token operator">$</span>value<span class="token punctuation">,</span> <span class="token string">" "</span><span class="token punctuation">)</span> <span class="token comment"># Visit left subtree</span> preorder_traversal<span class="token punctuation">(</span>node<span class="token operator">$</span>left<span class="token punctuation">)</span> <span class="token comment"># Visit right subtree</span> preorder_traversal<span class="token punctuation">(</span>node<span class="token operator">$</span>right<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Recursive post-order traversal (left, right, root)</span> postorder_traversal <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.null<span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token keyword">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Visit left subtree</span> postorder_traversal<span class="token punctuation">(</span>node<span class="token operator">$</span>left<span class="token punctuation">)</span> <span class="token comment"># Visit right subtree</span> postorder_traversal<span class="token punctuation">(</span>node<span class="token operator">$</span>right<span class="token punctuation">)</span> <span class="token comment"># Visit root</span> cat<span class="token punctuation">(</span>node<span class="token operator">$</span>value<span class="token punctuation">,</span> <span class="token string">" "</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test traversals</span> cat<span class="token punctuation">(</span><span class="token string">"In-order: "</span><span class="token punctuation">)</span> inorder_traversal<span class="token punctuation">(</span>tree<span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"\nPre-order: "</span><span class="token punctuation">)</span> preorder_traversal<span class="token punctuation">(</span>tree<span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"\nPost-order: "</span><span class="token punctuation">)</span> postorder_traversal<span class="token punctuation">(</span>tree<span class="token punctuation">)</span> |
Example: Calculate Tree Properties
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<span class="token comment"># Calculate height of tree</span> tree_height <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.null<span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> left_height <span class="token operator"><-</span> tree_height<span class="token punctuation">(</span>node<span class="token operator">$</span>left<span class="token punctuation">)</span> right_height <span class="token operator"><-</span> tree_height<span class="token punctuation">(</span>node<span class="token operator">$</span>right<span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">1</span> <span class="token operator">+</span> max<span class="token punctuation">(</span>left_height<span class="token punctuation">,</span> right_height<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Count nodes in tree</span> count_nodes <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.null<span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> return<span class="token punctuation">(</span><span class="token number">1</span> <span class="token operator">+</span> count_nodes<span class="token punctuation">(</span>node<span class="token operator">$</span>left<span class="token punctuation">)</span> <span class="token operator">+</span> count_nodes<span class="token punctuation">(</span>node<span class="token operator">$</span>right<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Sum all values in tree</span> sum_tree <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.null<span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> return<span class="token punctuation">(</span>node<span class="token operator">$</span>value <span class="token operator">+</span> sum_tree<span class="token punctuation">(</span>node<span class="token operator">$</span>left<span class="token punctuation">)</span> <span class="token operator">+</span> sum_tree<span class="token punctuation">(</span>node<span class="token operator">$</span>right<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test</span> cat<span class="token punctuation">(</span><span class="token string">"Tree height:"</span><span class="token punctuation">,</span> tree_height<span class="token punctuation">(</span>tree<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Number of nodes:"</span><span class="token punctuation">,</span> count_nodes<span class="token punctuation">(</span>tree<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Sum of values:"</span><span class="token punctuation">,</span> sum_tree<span class="token punctuation">(</span>tree<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> |
Part 6: Recursion vs. Iteration
Comparison with Factorial
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<span class="token comment"># Recursive factorial</span> factorial_recursive <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>n <span class="token operator">*</span> factorial_recursive<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Iterative factorial</span> factorial_iterative <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> result <span class="token operator"><-</span> <span class="token number">1</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token keyword">in</span> <span class="token number">1</span><span class="token operator">:</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> result <span class="token operator"><-</span> result <span class="token operator">*</span> i <span class="token punctuation">}</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Compare</span> n <span class="token operator"><-</span> <span class="token number">10</span> cat<span class="token punctuation">(</span><span class="token string">"Recursive:"</span><span class="token punctuation">,</span> factorial_recursive<span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Iterative:"</span><span class="token punctuation">,</span> factorial_iterative<span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token comment"># Performance comparison</span> n <span class="token operator"><-</span> <span class="token number">20</span> cat<span class="token punctuation">(</span><span class="token string">"\nPerformance comparison for n ="</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> <span class="token string">":\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Recursive:\n"</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>system.time<span class="token punctuation">(</span><span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token keyword">in</span> <span class="token number">1</span><span class="token operator">:</span><span class="token number">10000</span><span class="token punctuation">)</span> factorial_recursive<span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Iterative:\n"</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>system.time<span class="token punctuation">(</span><span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token keyword">in</span> <span class="token number">1</span><span class="token operator">:</span><span class="token number">10000</span><span class="token punctuation">)</span> factorial_iterative<span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
When to Use Recursion vs. Iteration
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<span class="token comment"># Problem: Flatten a nested list</span> nested_list <span class="token operator"><-</span> list<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> list<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> list<span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> list<span class="token punctuation">(</span><span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Recursive solution (elegant)</span> flatten_recursive <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>lst<span class="token punctuation">)</span> <span class="token punctuation">{</span> result <span class="token operator"><-</span> c<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>element <span class="token keyword">in</span> lst<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.list<span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Recursively flatten nested lists</span> result <span class="token operator"><-</span> c<span class="token punctuation">(</span>result<span class="token punctuation">,</span> flatten_recursive<span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment"># Base case: add non-list element</span> result <span class="token operator"><-</span> c<span class="token punctuation">(</span>result<span class="token punctuation">,</span> element<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Iterative solution (more complex)</span> flatten_iterative <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>lst<span class="token punctuation">)</span> <span class="token punctuation">{</span> result <span class="token operator"><-</span> c<span class="token punctuation">(</span><span class="token punctuation">)</span> stack <span class="token operator"><-</span> list<span class="token punctuation">(</span>lst<span class="token punctuation">)</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>length<span class="token punctuation">(</span>stack<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> current <span class="token operator"><-</span> stack<span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">]</span> stack <span class="token operator"><-</span> stack<span class="token punctuation">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>element <span class="token keyword">in</span> current<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.list<span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Push nested list onto stack for later processing</span> stack <span class="token operator"><-</span> c<span class="token punctuation">(</span>list<span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">,</span> stack<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment"># Add non-list element to result</span> result <span class="token operator"><-</span> c<span class="token punctuation">(</span>result<span class="token punctuation">,</span> element<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Compare</span> print<span class="token punctuation">(</span>flatten_recursive<span class="token punctuation">(</span>nested_list<span class="token punctuation">)</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>flatten_iterative<span class="token punctuation">(</span>nested_list<span class="token punctuation">)</span><span class="token punctuation">)</span> |
Part 7: Optimizing Recursion
Problem: Inefficient Fibonacci
The naive Fibonacci is extremely inefficient because it recalculates the same values many times:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<span class="token comment"># Count the number of calls</span> fib_counter <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">,</span> calls <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> calls <span class="token operator"><-</span> calls <span class="token operator">+</span> <span class="token number">1</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"fib(0) called\n"</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>list<span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> calls <span class="token operator">=</span> calls<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"fib(1) called\n"</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>list<span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> calls <span class="token operator">=</span> calls<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> cat<span class="token punctuation">(</span><span class="token string">"fib("</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> <span class="token string">") calling fib("</span><span class="token punctuation">,</span> n<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">") and fib("</span><span class="token punctuation">,</span> n<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">")\n"</span><span class="token punctuation">)</span> a <span class="token operator"><-</span> fib_counter<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">,</span> calls<span class="token punctuation">)</span> b <span class="token operator"><-</span> fib_counter<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">,</span> a<span class="token operator">$</span>calls<span class="token punctuation">)</span> return<span class="token punctuation">(</span>list<span class="token punctuation">(</span>value <span class="token operator">=</span> a<span class="token operator">$</span>value <span class="token operator">+</span> b<span class="token operator">$</span>value<span class="token punctuation">,</span> calls <span class="token operator">=</span> b<span class="token operator">$</span>calls<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> result <span class="token operator"><-</span> fib_counter<span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"\nTotal function calls:"</span><span class="token punctuation">,</span> result<span class="token operator">$</span>calls<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Fibonacci(10) ="</span><span class="token punctuation">,</span> result<span class="token operator">$</span>value<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> |
Solution 1: Memoization
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<span class="token comment"># Fibonacci with memoization</span> fib_memo <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">,</span> memo <span class="token operator">=</span> c<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment"># Check if already computed</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>length<span class="token punctuation">(</span>memo<span class="token punctuation">)</span> <span class="token operator">>=</span> n <span class="token operator">&&</span> <span class="token operator">!</span>is.na<span class="token punctuation">(</span>memo<span class="token punctuation">[</span>n<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>memo<span class="token punctuation">[</span>n<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Compute and store</span> result <span class="token operator"><-</span> fib_memo<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">,</span> memo<span class="token punctuation">)</span> <span class="token operator">+</span> fib_memo<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">,</span> memo<span class="token punctuation">)</span> <span class="token comment"># Update memo (simplified - need to pass back)</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Better: Use closure for memoization</span> create_fib_memoized <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> memo <span class="token operator"><-</span> c<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment"># memo[1] = fib(0), memo[2] = fib(1)</span> fib <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Adjust index (our memo starts with n=0 at position 1)</span> n_index <span class="token operator"><-</span> n <span class="token operator">+</span> <span class="token number">1</span> <span class="token comment"># Check if already computed</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>length<span class="token punctuation">(</span>memo<span class="token punctuation">)</span> <span class="token operator">>=</span> n_index<span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>memo<span class="token punctuation">[</span>n_index<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Compute recursively</span> result <span class="token operator"><-</span> fib<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> fib<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token comment"># Store in memo</span> memo <span class="token operator"><<-</span> c<span class="token punctuation">(</span>memo<span class="token punctuation">,</span> result<span class="token punctuation">)</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> return<span class="token punctuation">(</span>fib<span class="token punctuation">)</span> <span class="token punctuation">}</span> fib_fast <span class="token operator"><-</span> create_fib_memoized<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>fib_fast<span class="token punctuation">(</span><span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># This will be fast!</span> |
Solution 2: Tail Recursion
Tail recursion is when the recursive call is the last operation. R doesn’t optimize tail recursion, but it’s a good concept to understand:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span class="token comment"># Regular recursion (not tail-recursive)</span> factorial_normal <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>n <span class="token operator">*</span> factorial_normal<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Multiplication after recursive call</span> <span class="token punctuation">}</span> <span class="token comment"># Tail-recursive version (using accumulator)</span> factorial_tail <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">,</span> accumulator <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>accumulator<span class="token punctuation">)</span> return<span class="token punctuation">(</span>factorial_tail<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">,</span> n <span class="token operator">*</span> accumulator<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Recursive call is last</span> <span class="token punctuation">}</span> <span class="token comment"># Compare</span> cat<span class="token punctuation">(</span><span class="token string">"Normal:"</span><span class="token punctuation">,</span> factorial_normal<span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Tail: "</span><span class="token punctuation">,</span> factorial_tail<span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> |
Part 8: Common Recursion Patterns
Pattern 1: Divide and Conquer
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<span class="token comment"># Find maximum using divide and conquer</span> max_dc <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>vec<span class="token punctuation">)</span> <span class="token punctuation">{</span> n <span class="token operator"><-</span> length<span class="token punctuation">(</span>vec<span class="token punctuation">)</span> <span class="token comment"># Base cases</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">Inf</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment"># Divide</span> mid <span class="token operator"><-</span> floor<span class="token punctuation">(</span>n <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span> left_max <span class="token operator"><-</span> max_dc<span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token number">1</span><span class="token operator">:</span>mid<span class="token punctuation">]</span><span class="token punctuation">)</span> right_max <span class="token operator"><-</span> max_dc<span class="token punctuation">(</span>vec<span class="token punctuation">[</span><span class="token punctuation">(</span>mid <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">:</span>n<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment"># Conquer</span> return<span class="token punctuation">(</span>max<span class="token punctuation">(</span>left_max<span class="token punctuation">,</span> right_max<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test</span> numbers <span class="token operator"><-</span> sample<span class="token punctuation">(</span><span class="token number">1</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>numbers<span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Max:"</span><span class="token punctuation">,</span> max_dc<span class="token punctuation">(</span>numbers<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"- Check:"</span><span class="token punctuation">,</span> max<span class="token punctuation">(</span>numbers<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> |
Pattern 2: Backtracking
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<span class="token comment"># Generate all subsets of a set</span> generate_subsets <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>set<span class="token punctuation">,</span> index <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> current <span class="token operator">=</span> c<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">></span> length<span class="token punctuation">(</span>set<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> print<span class="token punctuation">(</span>current<span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Exclude current element</span> generate_subsets<span class="token punctuation">(</span>set<span class="token punctuation">,</span> index <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> current<span class="token punctuation">)</span> <span class="token comment"># Include current element</span> generate_subsets<span class="token punctuation">(</span>set<span class="token punctuation">,</span> index <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> c<span class="token punctuation">(</span>current<span class="token punctuation">,</span> set<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test</span> generate_subsets<span class="token punctuation">(</span>c<span class="token punctuation">(</span><span class="token string">"A"</span><span class="token punctuation">,</span> <span class="token string">"B"</span><span class="token punctuation">,</span> <span class="token string">"C"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
Pattern 3: Mutual Recursion
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span class="token comment"># Functions that call each other</span> is_even <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token boolean">TRUE</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>is_odd<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> is_odd <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token boolean">FALSE</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>is_even<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token keyword">in</span> <span class="token number">0</span><span class="token operator">:</span><span class="token number">5</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token string">"is even:"</span><span class="token punctuation">,</span> is_even<span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"| is odd:"</span><span class="token punctuation">,</span> is_odd<span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Part 9: Common Pitfalls and Solutions
Pitfall 1: Missing Base Case
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="token comment"># ❌ This will cause infinite recursion</span> bad_recursion <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Missing base case!</span> return<span class="token punctuation">(</span>bad_recursion<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># ✅ Always include a base case</span> good_recursion <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment"># Base case</span> return<span class="token punctuation">(</span>good_recursion<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Pitfall 2: Base Case Never Reached
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="token comment"># ❌ Base case unreachable for negative n</span> problematic <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>problematic<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Skips over 0 if n is odd</span> <span class="token punctuation">}</span> <span class="token comment"># ✅ Handle all cases</span> fixed <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment"># Handle all non-positive values</span> return<span class="token punctuation">(</span>fixed<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Pitfall 3: Stack Overflow for Deep Recursion
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<span class="token comment"># This will cause stack overflow for large n</span> deep_recursion <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span><span class="token number">1</span> <span class="token operator">+</span> deep_recursion<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># deep_recursion(100000) # Would cause stack overflow</span> <span class="token comment"># Solution: Use iteration for very deep recursion</span> iterative_alternative <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> result <span class="token operator"><-</span> <span class="token number">0</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token keyword">in</span> <span class="token number">1</span><span class="token operator">:</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> result <span class="token operator"><-</span> result <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">}</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Pitfall 4: Inefficient Recursion
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span class="token comment"># ❌ Inefficient - recalculates same values</span> fib_slow <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>n<span class="token punctuation">)</span> return<span class="token punctuation">(</span>fib_slow<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> fib_slow<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># ✅ Efficient with memoization</span> fib_fast <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">,</span> memo <span class="token operator">=</span> c<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>length<span class="token punctuation">(</span>memo<span class="token punctuation">)</span> <span class="token operator">></span> n<span class="token punctuation">)</span> return<span class="token punctuation">(</span>memo<span class="token punctuation">[</span>n <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> result <span class="token operator"><-</span> fib_fast<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">,</span> memo<span class="token punctuation">)</span> <span class="token operator">+</span> fib_fast<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">,</span> memo<span class="token punctuation">)</span> memo <span class="token operator"><<-</span> c<span class="token punctuation">(</span>memo<span class="token punctuation">,</span> result<span class="token punctuation">)</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Part 10: Performance Considerations
Measuring Recursion Depth
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<span class="token comment"># Function to measure recursion depth</span> measure_depth <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">,</span> depth <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span>strrep<span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">,</span> depth<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"Depth:"</span><span class="token punctuation">,</span> depth<span class="token punctuation">,</span> <span class="token string">"n ="</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span>strrep<span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">,</span> depth<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"← Base case reached\n"</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>depth<span class="token punctuation">)</span> <span class="token punctuation">}</span> max_depth <span class="token operator"><-</span> measure_depth<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">,</span> depth <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span>strrep<span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">,</span> depth<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"← Returning from depth"</span><span class="token punctuation">,</span> depth<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>max_depth<span class="token punctuation">)</span> <span class="token punctuation">}</span> max_depth <span class="token operator"><-</span> measure_depth<span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Maximum recursion depth:"</span><span class="token punctuation">,</span> max_depth<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> |
Time Complexity Comparison
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<span class="token comment"># Compare different recursion patterns</span> library<span class="token punctuation">(</span>microbenchmark<span class="token punctuation">)</span> n <span class="token operator"><-</span> <span class="token number">30</span> <span class="token comment"># Naive Fibonacci</span> fib_naive <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>n<span class="token punctuation">)</span> return<span class="token punctuation">(</span>fib_naive<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> fib_naive<span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Iterative Fibonacci</span> fib_iterative <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><=</span> <span class="token number">1</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>n<span class="token punctuation">)</span> a <span class="token operator"><-</span> <span class="token number">0</span> b <span class="token operator"><-</span> <span class="token number">1</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token keyword">in</span> <span class="token number">2</span><span class="token operator">:</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> temp <span class="token operator"><-</span> b b <span class="token operator"><-</span> a <span class="token operator">+</span> b a <span class="token operator"><-</span> temp <span class="token punctuation">}</span> return<span class="token punctuation">(</span>b<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Compare</span> print<span class="token punctuation">(</span>microbenchmark<span class="token punctuation">(</span> naive <span class="token operator">=</span> fib_naive<span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">,</span> iterative <span class="token operator">=</span> fib_iterative<span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">,</span> times <span class="token operator">=</span> <span class="token number">10</span> <span class="token punctuation">)</span><span class="token punctuation">)</span> |
Summary: The Recursion Philosophy
Recursion is your tool for solving problems that have a self-similar structure. Master these patterns:
-
Linear recursion – One recursive call (factorial, sum)
-
Tree recursion – Multiple recursive calls (Fibonacci, tree traversal)
-
Divide and conquer – Split problem into halves
-
Backtracking – Try all possibilities
-
Mutual recursion – Functions calling each other
Essential components of every recursive function:
-
Base case(s) – When to stop
-
Recursive case – How to break down the problem
-
Progress toward base case – Each call must get closer to stopping
Pros of recursion:
-
Elegant, mathematical solutions
-
Natural for recursive data structures (trees, nested lists)
-
Often simpler and more readable
Cons of recursion:
-
Can be slower (function call overhead)
-
Risk of stack overflow for deep recursion
-
Can be harder to debug
-
Not always intuitive
When to use recursion:
-
Tree/graph traversal
-
Divide-and-conquer algorithms
-
Backtracking problems
-
Mathematical definitions (factorial, Fibonacci)
-
Processing nested structures
When NOT to use recursion:
-
Simple iterative problems
-
Very deep recursion (thousands of levels)
-
Performance-critical code
-
When stack overflow is a concern
Recursion transforms how you think about problems. Instead of thinking “how do I loop through this?”, you start thinking “how is this problem a smaller version of itself?” It’s a shift from imperative to declarative thinking, and it’s one of the most beautiful concepts in computer science.
Would you like me to elaborate on any specific aspect of recursion or explore more complex recursive algorithms?
