CMPS 144 Spring 2022
Prog. Assg. #6: Recursive Saddleback Search
Due: 11:59pm, Monday, May 9

Background

10×11 matrix M
     0  1  2  3  4  5  6  7  8  9
   +-----------------------------+
 0 | 4  6  9 10 12 15 19 22 24 25|
 1 | 5 10 11 12 13 18 21 24 26 27|
 2 | 6 14 18 21 23 24 26 29 30 33|
 3 |10 15 19 24 25 27 31 34 36 37|
 4 |11 17 23 25 29 31 33 38 42 43|
 5 |15 18 27 29 30 32 35 42 46 50|
 6 |16 19 30 34 35 37 41 43 50 51|
 7 |20 23 32 37 41 43 44 47 52 53|
 8 |24 25 33 40 45 46 49 50 54 57|
 9 |26 29 34 41 48 51 55 58 60 62|
10 |30 33 38 43 52 56 58 61 64 67|
   +-----------------------------+

A characteristic of efficient search algorithms is that each probe results in a significant decrease in the size of the search space. As you will recall, in the binary search algorithm, each time an array element is probed (i.e., accessed and compared to the search key), the search space is cut in half. That algorithm exploits the fact that the array elements are in ascending order. (Indeed, binary search is not applicable unless the array elements are in ascending (or, alternatively, descending) order.)

Can the binary search algorithm be generalized to find occurrences of values in a two-dimensional array (i.e., matrix)? The answer is yes, assuming, of course, that its elements are properly ordered. For the purposes of this assignment, that will mean that the elements are strictly increasing along each row and along each column. An example of a 10×11 matrix —call it M— satisfying this condition is shown to the right.

Observe that, in any rectangular region of such a matrix, the largest value is found in its high corner (i.e., bottom right) and its smallest value is found in its low corner (i.e., upper left).

After one probe in search of 38
     0  1  2  3  4  5  6  7  8  9
   +-----------------------------+
 0 |              |15 19 22 24 25|
 1 |              |18 21 24 26 27|
 2 |  ELIMINATED  |24 26 29 30 33|
 3 |              |27 31 34 36 37|
 4 |              |31 33 38 42 43|
 5 |            30|32 35 42 46 50|
   +--------------+              |
 6 |16 19 30 34 35 37 41 43 50 51|
 7 |20 23 32 37 41 43 44 47 52 53|
 8 |24 25 33 40 45 46 49 50 54 57|
 9 |26 29 34 41 48 51 55 58 60 62|
10 |30 33 38 43 52 56 58 61 64 67|
   +-----------------------------+
To illustrate how one can apply the binary search concept to such a matrix, suppose that we wish to find the locations in M at which 38 occurs.

The low corner of M is at location (0,0) and its high corner is at location (10,9). We can compute the middle location to be ((0+10)/2, (0+9)/2), or (5,4). There we find 30, which is less than our search key, 38. It follows that 38 cannot possibly occur in the region whose high corner is (5,4), because all values in that region must be 30 or less. Which means that, as the result of this single probe, we can eliminate one-fourth of the search space from further consideration, as illustrated to the right.

The remaining search space (all of which must be searched if we are to be sure to find all locations in which 38 occurs) can be interpreted in three different ways:

  1. As three rectangular regions, namely
  2. As two rectangular regions, namely
  3. As two rectangular regions, namely

Of course, to search in any of the remaining rectangular regions, we can employ the same approach that got us this far. In other words, we search each of the remaining rectangular regions recursively! (The base case would be an empty region.)

After one probe in search of 20
     0  1  2  3  4  5  6  7  8  9
   +-----------------------------+
 0 | 4  6  9 10 12 15 19 22 24 25|
 1 | 5 10 11 12 13 18 21 24 26 27|
 2 | 6 14 18 21 23 24 26 29 30 33|
 3 |10 15 19 24 25 27 31 34 36 37|
 4 |11 17 23 25 29 31 33 38 42 43|
   |           +-----------------|
 5 |15 18 27 29|30               |
 6 |16 19 30 34|                 |
 7 |20 23 32 37|   ELIMINATED    |
 8 |24 25 33 40|                 |
 9 |26 29 34 41|                 |
10 |30 33 38 43|                 |
   +-----------+-----------------+
Now suppose that our search key had been 20 rather than 38. Then the conclusion that we would have drawn from our initial probe to location (5,4) (which contains 30) is that there is no need to perform any more probes within the region whose low corner is (5,4). The situation is shown to the right.

As before, we can interpret the remaining search space to be either a collection of three rectangular regions or, in two different ways, a pair of rectangular regions. In any case, we would then be left to recursively search the relevant regions.

The figures below attempt to generalize the examples described above and to address the possibility that the element probed happens to be the search key. The assumption is that a search for x is to be carried out within a rectangular region whose low corner has coordinates (LR,LC) and whose high corner has coordinates (HR,HC). The coordinates of the middle location are (MR,MC), where MR = (LR + HR)/2 and MC = (LC + HC)/2.

   LC           MC           HC
  +--------------+-------------+
LR|              |             |LR
  |              |             |
  |              |             |
  |  ELIMINATED  |             |
  |              |             |
  |              |             |
MR|            <x|             |MR
  +--------------+             |
  |                            |
  |                            |
  |                            |
  |                            |
HR|                            |HR
  +--------------+-------------+
   LC           MC           HC
   LC           MC           HC
  +----------------------------+
LR|                            |LR
  |                            |
  |                            |
  |                            |
  |                            |
  |             +--------------+
MR|             |>x            |MR
  |             |              |
  |             |              |
  |             |  ELIMINATED  |
  |             |              |
  |             |              |
HR|             |              |HR
  +-------------+--------------+
   LC           MC           HC
   LC           MC           HC
  +---------------+------------+
LR|               |            |LR
  |               |            |
  |  ELIMINATED   |            |
  |               |            |
  |               |            |
  |             +-+------------+
MR|             |x|            |MR
  +-------------+-+            |
  |             |              |
  |             |  ELIMINATED  |
  |             |              |
  |             |              |
HR|             |              |HR
  +-------------+--------------+
   LC           MC           HC
When middle
element < search key
When middle
element > search key
When middle
element = search key


A Possibly Better Approach

Notice how, if our probe of the region's middle element is lucky enough to find the search key there, fully half of the search space can be eliminated from further consideration. In the other two cases, only a fourth of that space can be eliminated. It is a huge advantage, in terms of minimizing the number of probes performed during a search, to be able to eliminate half of the search space, as opposed to only one-fourth.

But perhaps we can make our own luck! Suppose that instead of simply probing the middle element of the region being searched, we performed a binary search within that region in order to find a pair of adjacent locations whose values are, respectively, less than and not less then, the search key. Such a search could take place within, say, the middle row of the region. The result of such a search allows us to eliminate fully half the search space, like this:

   LC            c          HC
  +-------------+-------------+
LR|             |             |LR
  |             |             |
  |  ELIMINATED |             |
  |             |             |
  |             |             |
  |             +-------------+
MR|            <|≥            |MR
  +-------------+             |
  |             |             |
  |             |  ELIMINATED |
  |             |             |
  |             |             |
HR|             |             |HR
  +-------------+-------------+
   LC            c          HC

To clarify, here we performed a binary search within the middle row MR of the indicated region of matrix M to find c satisfying the condition that M[MR][c−1] < x and M[MR][c] ≥ x.

Having found c, fully half of the search space can be eliminated. Of course, finding c costs about lg(HC−LC+1) probes (in performing binary search upon a row of length HC−LC+1) rather than only one. An interesting question is whether performing a logarithmic number of probes to be able to eliminate half the search space results in a fewer total number of probes than does using one probe for the purpose of eliminating one-fourth of the search space.

Note: One must also allow for these possibilities:

Although one might fairly call these special cases, it is not necessarily true that they must be treated totally differently from the "normal" case.


The Assignment

Provided are the following Java classes, the last of which is in need of completion.


Sample Execution of SB_Tester

$ java SB_Tester
Welcome to the RecSaddleBackSearcher tester.
Enter # rows in matrix: 9
Enter # columns in matrix: 11
Enter seed for pseudorandom # generation: 5

        0   1   2   3   4   5   6   7   8   9  10
    +--------------------------------------------
   0|   5   8  13  18  20  21  26  28  31  33  35
   1|   9  12  17  19  24  26  28  31  32  36  37
   2|  12  13  22  25  28  33  36  37  39  43  48
   3|  13  17  27  29  30  36  38  42  45  48  52
   4|  17  18  28  30  33  39  43  46  51  52  55
   5|  18  20  33  35  38  41  47  48  55  58  63
   6|  22  26  38  40  44  45  48  51  60  61  67
   7|  23  31  39  44  49  53  55  57  64  66  69
   8|  26  34  43  46  50  55  56  58  67  72  77

Enter a search key (or Q, or S): 20
The search for 20 involved 21 probes and yielded this list of locations:
[(5,1), (0,4)]

Enter a search key (or Q, or S): 73
The search for 73 involved 17 probes and yielded this list of locations:
[]

Enter a search key (or Q, or S): 33
The search for 33 involved 29 probes and yielded this list of locations:
[(4,4), (5,2), (2,5), (0,9)]

Enter a search key (or Q, or S): S

        0   1   2   3   4   5   6   7   8   9  10
    +--------------------------------------------
   0|   5   8  13  18  20  21  26  28  31  33  35
   1|   9  12  17  19  24  26  28  31  32  36  37
   2|  12  13  22  25  28  33  36  37  39  43  48
   3|  13  17  27  29  30  36  38  42  45  48  52
   4|  17  18  28  30  33  39  43  46  51  52  55
   5|  18  20  33  35  38  41  47  48  55  58  63
   6|  22  26  38  40  44  45  48  51  60  61  67
   7|  23  31  39  44  49  53  55  57  64  66  69
   8|  26  34  43  46  50  55  56  58  67  72  77

Enter a search key (or Q, or S): Q
Goodbye from the RecSaddleBackSearcher tester.