CMPS 144L Lab Activity
Array Sum, Recursively

The most obvious recursive solution to the problem of summing the elements in array segment a[low..high) (of numbers) is based upon the observation that, if the array segment is not empty (i.e., low < high), the sum of its elements is obtained by adding a[low] to the sum of the elements in a[low+1..high). (Or, alternatively, you can add the sum of the elements in a[low..high-1) and a[high-1].)

This observation can be generalized to say that, for any m satisfying low < m < high, the sum of the elements in a[low..high) is obtained by adding the sum of the elements in a[low..m) to the sum of the elements in a[m..high). With respect to computational resources, namely space (i.e., memory), it turns out that this approach is most efficient when m is chosen to be halfway between low and high.

Based upon this, complete the sumOfAux() method in the ArraySumRec application. Beware the case of the array segment of length one. "Print" statements are present in the method for the purpose of narrating its execution, which might help you in debugging.

12
-4 5 13 23 -2 0 -5 8 27 2 65 15
If run arguments are provided to the main() method, it interprets them as being the numbers to be placed into an array and summed. Otherwise, the program prompts the user to enter the name of a file containing the description of the array whose elements are to be summed. Here is such a file, and it is shown to the right. The first number in the file, call it N, indicates the length of the array to be created. The following N numbers are placed in the array, which is then summed. (Two other files containing descriptions of arrays are ary_input2.txt and ary_input3.txt.


Narration Example

Below is the narration produced by the sumOf() (really, sumOfAux()) method when applied to the array of length nine described in ary_input2.txt. (Well, the first three lines are produced by the main() method before it calls sumOf().)

You will notice —assuming that you have done the "narration versions" of the recursive methods in the previous activities of this lab— that the indentation pattern looks very different from that of the other recursive methods you've worked on. That's because this one's recursive case involves two recursive calls to itself, rather than only one. And that is because the recursive case solution is described in terms of the solutions of two smaller instances of the same problem (i.e., the problem of summing the elements of an array segment) rather than only one.

Moreover, by describing the recursive case solution in terms of the solutions of two equal-sized smaller instances of the problem, we minimize the depth to which the recursion descends, which means that we minimize the size to which the run-time stack must grow (thereby minimizing memory usage).

For the example shown —involving an array of length nine— that depth is only four (taking the initial instance to be at depth zero). In general, the depth will be bounded above by ⌈log2 N⌉, where N is the size of the initial problem instance. For even moderate values of N, that is a much smaller depth than N−1, which is what you would get using a recursive solution based upon the equation

sumOf(a[low..high)) = a[low] + sumOf(a[low+1..high))

Here is what a run of the program, when applied to the data in ary_input2.txt, should look like:

Enter name of input file: ary_input2.txt
The array is as follows:
[5, -2, 6, 34, 19, 8, 4, -7, 14]

Entering sumOfAux() to compute sum of b[0..9)
   Entering sumOfAux() to compute sum of b[0..4)
      Entering sumOfAux() to compute sum of b[0..2)
         Entering sumOfAux() to compute sum of b[0..1)
         Leaving sumOfAux(); sum of b[0..1) found to be 5
         Entering sumOfAux() to compute sum of b[1..2)
         Leaving sumOfAux(); sum of b[1..2) found to be -2
      Leaving sumOfAux(); sum of b[0..2) found to be 3
      Entering sumOfAux() to compute sum of b[2..4)
         Entering sumOfAux() to compute sum of b[2..3)
         Leaving sumOfAux(); sum of b[2..3) found to be 6
         Entering sumOfAux() to compute sum of b[3..4)
         Leaving sumOfAux(); sum of b[3..4) found to be 34
      Leaving sumOfAux(); sum of b[2..4) found to be 40
   Leaving sumOfAux(); sum of b[0..4) found to be 43
   Entering sumOfAux() to compute sum of b[4..9)
      Entering sumOfAux() to compute sum of b[4..6)
         Entering sumOfAux() to compute sum of b[4..5)
         Leaving sumOfAux(); sum of b[4..5) found to be 19
         Entering sumOfAux() to compute sum of b[5..6)
         Leaving sumOfAux(); sum of b[5..6) found to be 8
      Leaving sumOfAux(); sum of b[4..6) found to be 27
      Entering sumOfAux() to compute sum of b[6..9)
         Entering sumOfAux() to compute sum of b[6..7)
         Leaving sumOfAux(); sum of b[6..7) found to be 4
         Entering sumOfAux() to compute sum of b[7..9)
            Entering sumOfAux() to compute sum of b[7..8)
            Leaving sumOfAux(); sum of b[7..8) found to be -7
            Entering sumOfAux() to compute sum of b[8..9)
            Leaving sumOfAux(); sum of b[8..9) found to be 14
         Leaving sumOfAux(); sum of b[7..9) found to be 7
      Leaving sumOfAux(); sum of b[6..9) found to be 11
   Leaving sumOfAux(); sum of b[4..9) found to be 38
Leaving sumOfAux(); sum of b[0..9) found to be 81
As computed by sumOf(), its elements sum to 81

The picture below is a graphical depiction of the "call tree". Each node in the tree represents a call to sumOfAux() and is labeled by the range of integers [low..high) specifying the boundaries of the array segment that it is responsible to process. The nodes at the bottom (i.e., the leaf nodes) correspond to "base-case instances" of the method.

                          [0..9)
                         /      \
                        /        \
                       /          \
                      /            \
                     /              \
                    /                \
                   /                  \
                  /                    \
                 /                      \
                /                        \
           [0..4)                        [4..9)
           /    \                        /    \
          /      \                      /      \
         /        \                    /        \
        /          \                  /          \
       /            \                /            \
   [0..2)         [2..4)          [4..6)         [6..9)
     / \            / \            /  \           /  \
    /   \          /   \          /    \         /    \
[0..1) [1..2)  [2..3) [3..4)   [4..5) [5..6)  [6..7) [7..9)
                                                      /  \ 
                                                     /    \ 
                                                  [7..8) [8..9)