# Lab: Traversing 2D Data Structures Using Iterators

## Introduction

In this lab you will implement the iterators for several algorithms that step through (traverse) a two-dimensional data structure made up of rows and columns. These algorithms are useful for many different kinds of two-dimensional data structures.

The two-dimensional data structure used in this lab is represented by a `BoundedGrid` object made up of rows and columns. A `BoundedGrid` object models a bounded rectangular grid that contains objects at various grid locations. Each cell contains zero or one objects.  In this program, cells that are not empty will contain color blocks (objects of the `ColorBlock` class).

0 1 2 3 4 5 6 7 8
0
 obj1 obj2 obj3 obj4 obj5
1
2
3

We refer to locations in the grid by their row and column numbers in parentheses, such as location (2, 7). Row and column numbers start at 0 rather than 1, so location (0, 0) refers to the first row and first column. Object `obj1` in the grid shown above is in the first row and fourth column, or at location (0, 3). Object `obj5` is at location (3, 8). (This is similar to the way Java array and `ArrayList` indices are numbered.)

A traversal through a two-dimensional data structure is an algorithm that steps through all the elements of the data structure, visiting each element exactly once.  A traversal through a grid steps through all the locations in the grid.  There are many different ways to traverse through a grid.  One common type of traversal is a row-major traversal, which steps through the grid row-by-row.  It first visits all the locations in row 0, then all the locations in row 1, and so on.  Another common traversal is a column-major traversal, which steps through the grid column-by-column.  It first visits all the locations in column 0, then all the locations in column 1, and so on.

In this lab you will define iterator classes that implement various traversal algorithms.  For example, the following simple code uses the `RowMajorGridIterator` iterator, which steps through a grid in row-major order.

``````    RowMajorGridIterator it = new RowMajorGridIterator(env);
while ( it.hasNext() )
{
Location nextLoc = (Location) it.next();
new ColorBlock(highlightColor, env, nextLoc);
}``````

The iterator classes you define will be used in a program that defines buttons for the various traversal algorithms and then illustrates each algorithm by placing color block objects in the grid in the order of the traversal.  Not all of them will be true traversals, in which every location is visited exactly once, but all will step through grid locations in some specific pattern.

## Getting Started

In this lab you will be implementing new iterator classes and adding them to the list of iterators used by the `IteratorLab` application. The first thing to do, therefore, is to download the existing code for this application.

#### Exercise Set 1

1. Download the zip file that contains the starting code files for the Grid Iterator Lab (`GridIterator.zip`) and unzip it. You will see the following files and folders.
• The `Instructions` folder contains this write-up (GridIterator.shtml).
• The `grid.jar` Java archive (`jar`) file contains a library of classes that can be used to model a two-dimensional grid as described above.
• `BoundedGrid` (class that represents the two-dimensional grid)
• `Location` (class that represents the row and column positions of a location in the grid)
• `ColorBlock` (class whose objects represent blocks of color put in a grid)
• The `GridPkgClassDocumentation` folder contains the class documentation for the classes in the `grid.jar` library.
• The `JavaSourceFiles` folder contains the source files for the Grid Plotter program in which we can draw pictures by placing (plotting) color blocks in a grid.
• `IteratorLab` (contains the `main` method)
• `GridIterator` class (the abstract iterator class you will be extending)
• `RowMajorGridIterator` (an iterator class that implements a row-major traversal; you can use this as a template for other iterator classes)
• `ColMajorGridIterator` (a skeleton iterator class that you fill in)
• `IteratorGUI` (a class that implements the program's graphical user interface; you are not expected to read or understand this class)
• `IterationController` (a class used by the program's graphical user interface to control the traversals; you are not expected to read or understand this class)
• You can find documentation for these files in the `GridIteratorClassDocumentation` folder.

Note: All of the classes in the `JavaSourceFiles` folder and the `grid.jar` Java archive file are covered by the GNU General Public License.

2. Compile and run the program. As the program starts up you will be asked for the dimensions (number of rows and columns) of the grid in which you will be drawing. For now you can go with the default values, since your purpose for this exercise is just to experiment with the user interface. Once you have chosen the grid dimensions, click on the "Row-Major Order" button, you should see color blocks filling the locations of the grid in row-major (top-down, left-to-right) order. Experiment with the speed adjustment slider while the program is drawing color blocks.

3. Experiment with the program to discover what the "Create New Grid" and "Clear" buttons and the "Background Color" and "Drawing Color" menus do. What happens if you press the "Row-Major Order" button twice in a row?

4. Experiment with the "Column-Major Order" button.  What is printed to `System.out`?  What happens if you click on the "Stop" button after a couple of iterations?  What happens if you let the traversal run indefinitely?

## Studying the Algorithms

The starting point of the Grid Iterator application is the `IteratorLab` class, which contains the `main` method.  Look over the class.   It defines two constants that define the size of the window containing the graphical user interface and two more that define the extreme values for the speed adjustment slider.  The class's `main` method establishes what traversal algorithms are supported and then creates the graphical user interface and makes it visible on the screen. The `IterationController.register` method is a class method that associates an algorithm name (which becomes the label on a button) with the iterator class that implements that algorithm.

#### Exercise Set 2

1. Experiment with the constants defined at the top of the `IteratorLab` class to see how changing them affects the application.

Next, look at the `ColorBlock` class, which pairs a color and location together. The `Color` class is a standard Java class found in `java.awt`. You can create a color by specifying amounts of red, green, and blue (values between 0 and 255), or you can use one of the predefined colors provided in the class, such as `Color.red`. The `Location` class comes from the AP® Marine Biology Case Study.

 `java.awt.Color` Class (Selected Constants and Methods) ```BLACK, BLUE, CYAN, GRAY, GREEN, MAGENTA, ORANGE, PINK, RED, WHITE, YELLOW Color(int r, int g, int b)```

#### Exercise Set 3

1. What aspects of the `ColorBlock` class allow its objects to be put in a grid?  How do `ColorBlock` objects get added to a grid?  Is the `ColorBlock` class needed?  Couldn't we just put `Color` objects in a grid?

Finally, we get to the heart of the `IteratorLab` application, the set of traversal algorithms it supports.  These are implemented using iterators that step through a grid, as in the code example in the Introduction section of this lab.  The `GridIterator` abstract class partially implements the standard Java `Iterator` interface; the `RowMajorGridIterator` class is one example of a concrete subclass of `GridIterator` that completes the implementation.  In particular, the `Iterator` interface specifies that all iterator classes need to define `hasNext` and `next` methods (used in the code example in the Introduction).  The abstract `GridIterator` class implements these methods, but the implementation of the `next` method makes use of a protected, unimplemented `findNextLocation` method.  This method must be implemented in concrete subclasses of `GridIterator`, such as `RowMajorGridIterator`.  The way `findNextLocation` is implemented in each concrete subclass determines how the iterator traverses the grid.  Each concrete subclass of `GridIterator` must also provide a constructor that takes a `BoundedGrid` as a parameter, since that is what the `TraversalGUI` object assumes is available when it tries to construct a concrete iterator object.

#### Exercise Set 4

1. Does the code example in the Introduction section behave correctly if the grid is empty?

2. Can you create an `Iterator` instance?  A `GridIterator` instance?  A `RowMajorGridIterator` instance?

3. Looking at the `GridIterator` class, what is the first location returned by the `next` method?  Does this depend on the specific implementation of `findNextLocation` used by an iterator object?

4. How do the statements in the `findNextLocation` method of the `RowMajorGridIterator` class ensure that the order in which the application highlights cells will be row-major order?

Now it's time to write some iterators for traversal algorithms of your own.

#### Exercise Set 5

1. Complete the `ColMajorGridIterator` class, using `RowMajorGridIterator` as a guide. Test your class by running the program and watching the traversal. Are the cells highlighted left-to-right, going down each column?

2. Create a `ReverseRowMajorGridIterator` class, using `RowMajorGridIterator` as a guide. This algorithm should highlight cells bottom-up, going left-to-right across each row. In other words, the row order is reversed, but the column order is not. Edit the main method in the IteratorLab class to register your new class with an appropriate name.  Test your new class by running the program and watching the traversal.   Remember that each concrete subclass of `GridIterator` must provide a constructor that takes a `BoundedGrid` as a parameter.  That constructor could use either of the constructors in `GridIterator`: the one that takes only a bounded grid as a parameter, or the one that takes both a bounded grid and a starting location.

3. Create a `ReverseColMajorGridIterator` class, using `ColMajorGridIterator` as a guide. This algorithm should highlight cells right-to-left, going up each column from the bottom. In other words, both the row and column orders should be the reverse of `ColMajorGridIterator`. Test your new class.

4. Create a `Diagonal` class. This algorithm should highlight cells along the diagonal from the upper-left corner to the lower-right corner.** Again, it is not a true traversal of the grid.  Before you attempt to write the code, list the locations that you want the iterator to visit. When you're done with the implementation, test your new class.
**The diagonal algorithm goes to exactly the lower-right corner only if the grid is square.  If it is not square, the algorithm traverses down and to the right until it comes to the last column or the last row, depending on whether the grid is higher than it is wide or wider than it is high. The diagrams below show the behavior for a 5 x 5 grid, a 3 x 5 grid, a 5 x 3 grid, and a 1 x 1 grid.

5. Create a `Triangle` class. This algorithm should highlight (fill in) all the cells below the diagonal you produced in the preceding exercise. (It will form a true triangle only if there are at least as many columns in the grid as there are rows.)  Before you attempt to write the code, list the locations that you want the iterator to visit. When you're done with the implementation, test your new class. The diagrams below show the behavior for a 5 x 5 grid, a 3 x 5 grid, a 5 x 3 grid, and a 1 x 1 grid.

6. Create a `DoubleDiagonal` class. This algorithm should highlight the cells along the two diagonals, from the upper-left corner to the lower-right corner** and from the upper-right corner to the lower-left corner.** If the grid has an odd number of columns, the two diagonals will cross at a single location, but your "iterator" should not return that location twice.  Before you attempt to write the code, list the locations that you want the iterator to visit. When you're done with the implementation, test your new class. (**Again, whether the algorithm goes exactly to the opposite corner depends on whether the grid is square.)  The diagrams below show the behavior for a 5 x 5 grid, a 4 x 5 grid, a 5 x 4 grid, and a 1 x 1 grid.

Hints: You can draw the double diagonal by drawing a line from the upper-left corner down and to the right and drawing a line from the upper-right corner down and to the left.  OR, you can visit both locations in the first row, followed by both locations in the 2nd row, etc.  This algorithm may be easier.  You know one of the two locations in each row from your implementation of the `Diagonal` class, and you can calculate the other from it, given the number of columns in each row.   You'll need a way of recognizing whether you're visiting the first location in a row, in which case the next location should be the other location in the row, or visiting the second location, in which case the next location will be on the next row.  If both locations are the same location (single cross-over point), then you do not want to visit it twice.

7. Create a `PerimeterTraversal` class. This algorithm should highlight the cells along the four sides of the grid, but not the interior cells. This is actually a traversal of the grid's perimeter rather than of the grid as a whole, because you will not be visiting every location in the grid.   Before you attempt to write the code, list the locations that you want the iterator to visit in order to find a pattern. When you're done with the implementation, test your new class.  The diagrams below show the behavior for a 5 x 5 grid, a 2 x 5 grid, a 3 x 1 grid, and a 1 x 1 grid.

8. Create a `SpiralTraversal` class. This algorithm should highlight the cells along the perimeter of the grid, then spiral in and highlight the cells along the perimeter of the unhighlighted cells, then spiral in again and highlight the next perimeter of unhighlighted cells.  Continue in this way until you have visited every location in the grid.   Before you attempt to write the code, list the locations that you want the iterator to visit in order to find a pattern. When you're done with the implementation, test your new class.

9. Create a `Butterfly` class. This algorithm should highlight the cells in the left and right side quadrants formed by the double diagonal you produced in Exercise 6. Before you attempt to write the code, list the locations that you want the iterator to visit. When you're done with the implementation, test your new class. (See previous exercises to read more about square and non-square grids.)  The diagrams below show the behavior for a 5 x 5 grid, a 4 x 5 grid, a 5 x 4 grid, and a 1 x 1 grid.