I think there are two separate aspects to understanding recursion:

- How to use recursion to solve problems
- How recursion is evaluated

## How to use recursion

Let's look at an example: maximum depth of a binary tree (where a tree with a single node is depth 1). A recursive solution in python might look like this:

```
def max_depth(root):
if root is None:
return 0
return 1 + max(max_depth(root.left), max_depth(root.right))
```

You don't need to think about how this is actually evaluated; you just define it how you would mathematically. If I *somehow* know that the maximum depth of the left branch is $x$ and the maximum depth of the right branch is $y$ and that $x > y$ (without loss of generality), then I know that the maximum depth of the entire tree is $1 + x$. This way of thinking about problems is one way you can use recursion.

Of course, you need to make sure that the inputs to the recursive calls are in some way smaller than the input to the function that makes the recursive call, which segues into how recursion is evaluated.

## How recursion is evaluated

To think about how recursion is evaluated, we can use the same example. In the example above, there are pending recursive calls, waiting to return (note that recursion does not necessarily have this, see tail call). To see this, suppose our tree looks like this

```
O <- root
/ \
O O
/ \
O O
```

and you have a variable r storing the root. If you call `max_depth(r)`

, it will try to evaluate the else clause; it will evaluate `max(max_depth(r.left), ...)`

and then add 1 to that result. To the `r.left`

recursive call, the input looks like this

```
O
/ \
O O
```

And for the `r.right`

recursive call, it is simply this:

```
O
```

The `r.left`

recursive call evaluates else clause, which means it tries to evaluate the max depth of the left and right subtrees, and add 1 to whichever is greater.

The `r.right`

recursive call also evaluates the else clause.

So at this point you think of the return value of the original call to max_depth looking like this:

```
return 1 + max(
1 + max(max_depth(root.left.left), max_depth(root.left.right),
1 + max(max_depth(root.right.left), max_depth(root.right.right))
)
```

Both recursive calls of the left branch have trees that look like this now

```
O
```

while both recursive calls of the right branch, since it was just a node without any children, have trees that are empty, which is `None`

in Python. Thus, they fall to the base-case, which means it is evaluated as 0.

So now the original return value is like this

```
return 1 + max(
1 + max(
1 + max(max_depth(root.left.left.left), max_depth(root.left.left.right)),
1 + max(max_depth(root.left.right.left), max_depth(root.left.right.right))
),
1 + max(
0,
0
)
)
```

All recursive paths from the right branch already reached the base-case, and now on this recursive call, all children of the left branch will as well, which means the return value of the original function is now

```
return 1 + max(
1 + max(
1 + max(
0,
0
),
1 + max(
0,
0)
),
1 + max(
0,
0
)
)
```

which evaluates to

```
return 1 + max(
1 + max(
1 + 0,
1 + 0
),
1 + 0
)
```

and

```
return 1 + max(
1 + 1,
1 + 0
)
```

and

```
return 1 + 2
```

finally

```
3
```

Note, this evaluation was not performed according to any formal evaluation model (see substitution model or environment model); it was merely to help build intuition for how evaluation could be done.

**Extra (tail-recursion)**: I mentioned earlier about how recursion does not necessarily have these pending function calls that must be recursed back to once they finally have the result of the recursive call. Consider a recursive function to find the sum of a list (ignoring the python built-in `sum()`

):

```
def sum_list(lst):
if lst == []:
return 0
return lst[0] + sum_list(lst[1:])
```

This indeed would have pending recursive calls, as it waits to add lst[0] to the result of the recursive calls. We can make this tail-recursive by accumulating the sum of the list in an argument that is simply returned unmodified at the end:

```
def sum_list_tail_recursive(lst, result):
if lst == []:
return result
return sum_list_tail_recursive(lst[1:], result + lst[0])
```

Once this evaluation reaches the base-case, it has the the result of the original call to `sum_list()`

, and it does not need to be added to, or modified in any way as you recurse back up, and so if a compiler/interpreter recognizes this, it can optimize by skipping directly to the first call, eliminating the need to recurse back to it step-by-step.

4

You may find this discussion helpful.

– Miles – 2017-05-23T20:25:03.307Find the file named "ThisIsIt" but only if it is at the bottom-most node of a tree-structured directory. – Bob Brown – 2018-05-06T22:13:05.503

It is like teaching recursion. – ctrl-alt-delor – 2018-09-08T11:13:39.070

A recursive program is a program that calls itself recursively. – JosephDoggie – 2018-09-18T16:02:58.870

1curse = to abuse something verbally. recurse = to repeat oneself while abuse something verbally – pojo-guy – 2017-07-03T23:43:54.457

Do you have any specific language you are using? – naru sin – 2017-05-23T15:02:26.913

2

There is a question about recursion here https://cseducators.stackexchange.com/questions/17/analogy-for-teaching-recursion

– ctrl-alt-delor – 2017-05-28T16:17:34.9107This is language agnostic, I'm really looking forward to ways for students to grasp the concept of recusion – pluke – 2017-05-23T15:03:14.630

How about Fractals?

– Quazi Irfan – 2017-05-23T15:08:45.480Fractals are nice, but it doesn't get away from my problem of not having an end state / goal – pluke – 2017-05-23T15:09:31.047

You've ordered things, and you receives a parcel. It is a cardbox containing things, some of them are enclosed in cardboxes. Boxes may contain other (obviously smaller) cardboxes. – Michel Billaud – 2017-07-21T12:06:51.367

You've posted a message, which now has other messages as answers. Answer themselves may have answers, etc. – Michel Billaud – 2017-07-21T12:07:52.410

This was a great question. I hope we hear more from you! – Ben I. – 2017-06-02T15:34:46.397

7

Wait, what's recursion again? Okay, Google "recursion"... huh, it gives "_Did you mean: recursion_"? Okay, clicking that... huh, it gives "_Did you mean: recursion_"? Okay, clicking that... huh, it gives "_Did you mean: recursion_"? Okay, clicking that... huh, it gives "_Did you mean: recursion_"? Opps, out of characters - stack overflow!

– Nat – 2017-05-23T15:27:21.753To teach recursion, I first teach iteration, then I teach recursion. – Michel Billaud – 2017-10-06T13:43:59.853

There are lot's of good suggestions below. I would suggest using an example that does not admit an easy iterative solution. Bonus points if it does not use tail-recursion. – Jive Dadson – 2018-01-14T04:56:52.130