Activity 13-2 - Stacks for Recursion



How does recursion work?  As we mentioned in the P13_1.cpp, coming back from the base we didn't display 4 asterisks.  Somehow we knew that we had to display 3, because the integer division of 7/2 = 3, and indeed that was what we displayed.  How did we know about 3?

In order to track recursion, and a number of other things, most computer systems use a data structure called a stack.  A stack is a very specialized memory structure that is analogous to a stack of paper.  As there is a limited number of papers in hand, there is also a limited number of memory structures one can use to do recursion.  Thus, a recursion process may require more memory than is available on your computer, which results in failure.  The idea is that every time the computer wants to place more information in the stack, it requires a blank memory space, just like a blank sheet of paper.  To get information out of the stack, the top sheet will be read first, once it is no longer needed, it will be thrown away, and the next sheet becomes available.  The top sheet is the last thing you have put on the stack, and it will be the first one that gets read.  This is called a last-in/first-out memory structure.  In a computer system instead of sheets of paper, we will use memory frames.

Using a stack, your computer can keep track of recursion processes.  Every time a function is called, a new frame is taken, the function definition is copied to the frame, and the arguments are plugged in for the function parameters.  Then, the computer starts executing the body of the function definition.  Once it encounters a recursive call (calling itself), it will halt the computation it is doing and will wait for the value to get returned from the recursive call.  But, before it proceeds with the recursive computation, it saves enough information such that when it is back from the recursive computation, it can continue the halted computation.

If we use the pow function to compute the value for 24, we would have something that looks like this:

pow(2,4) = 2*pow(2,3) = 2*8 = 16                                                                Forward Step 1/Backward Step 4
                     pow(2,3)= 2*pow(2,2) = 2*4 = 8                                              Forward Step 2/Backward Step 3
                                          pow(2,2) = 2*pow(2,1) = 2*2 = 4                        Forward Step 3/Backward Step 2
                                                                pow(2,1) = 2*pow(2,0) = 2*1 =2   Forward Step 4/Backward Step 1
                                                                                      pow(2,0) = 1             Base or stopping case (use it to go up)

The pow function looks something like the following (please note that we have used power for the function name to avoid a conflict with the standard pow function in cmath).

int power(int x, int n)
{
         if(n < 0)
        {
                cout << "Illegal argument to power \n";
                exit(1);
        }

        if(n > 0) // Recursive process
                return( power(x, n-1)*x);
        else  // Stopping case
                return (1);
}

So, when in the main we call power(2,4), a new frame will be picked, the value of x will be set to 2 and value of n will be set to 4.  The body of the function is copied to the frame.  We now have remembered the values for x and n and we have the body of the function.  We execute the function for these two values.  Since n is not less than 0, we execute the statement after if(n > 0), i.e., call function power again, return( power(x, n-1)*x); thus, we will have a new frame but this time the call will be made as power(2,3) and the current computation will be halted.  Now at the top of the stack we will have the frame that contains the information for power(2,3). The process continues and the top frame in the stack changes until we get to power(2,0).  When we execute this one, since n is not larger than 0, we will go to the else and the function returns 1.  That is where we stop going further down the chain and we no longer make recursive calls to the function.  Now it is time to pick frames from the top and replace the function with the returned value.  At the time you call the function as power(2,0), the top frame is power(2,0). So you replace that with 1 and then throw away that frame.  Then you will have the power(2,1) which will be replaced by 2*1 (it was 2*power(2,0) ).  Now we have a value for power(2,1).  We keep moving up the same way and as we go up we will discard the frames until there are no more frames on the stack.  By then the last frame power(2,4) = 16 is reached.

Exercise 13.2
Take a blank sheet of paper and cut it in 8 pieces.  Number them from top to bottom, 1 through 8.  We will pretend that this is the stack system.  Now try to implement the recursion process for computing 24.  You only need 6 of these pieces but, in reality, your stack may have a few extra blank frames any way.

Note that every time you call a function, you need to get a new page.  Since it takes time to copy the body of the function on the paper, for now just make a note of the statement that you will execute in each case.