Computer Science 210 Lab 6: Stacks and Queues
Due: October 28, 1997

Objectives and Overview: Stacks and queues are special linear data structures that restrict the way in which elements can be added and deleted. Yet, these simple data structures have surprisingly wide utility in computer science and modeling applications. We shall explore the properties and some of the applications of stacks and queues in this lab.

Part 1 - Running a Maze

Start CodeWarrior and create a new project called Lab6.µ on the desktop. Make a copy of the MazeRunner.java program file from the CS210 (Tucker) -> examples folder and add it to your project. Also copy and add the file structure.zip, which can be found in the CS210 (Tucker) folder, to your project.

To run this program, add a copy of the file fig8.8 from the CS210 (Tucker) folder to your project folder (not your project), and be sure that the Edit -> Target Settings have MazeRunner as the main class and fig8.8 as the parameters.

Now make and run this program to be sure that it works. A sample output of the program for the input maze in Figure 8.8 is shown below:

####################
#s#       #f...#...#
#.####### ####.#.#.#
#.........#..#.###.#
##### ###.#........#
#   # #...#######.##
#   # #.### #...#..#
#   # #.#...#.#.##.#
#     #...#...#....#
####################

Here, each position of the maze is identified by an integer pair, [i] [j], denoting its row and column number. The starting position is marked with an s and the finishing position is marked with an f. The above display shows a solution by a series of dots (.) from the starting position to the finishing position. In this example, the starting positon is [1] [1] and the finishing position is [1] [11], and the solution path visits positions [2] [1], [3] [1]. [3] [2], [3] [3], and so forth.

Two auxiliary classes are used to facilitate this program, the Maze class and the Position class. The Maze class takes care of reading a maze from an ASCII text file, and also identifies whether a position in the maze is clear or has already been visited. Its methods are summarized on page 141 of your text. The Position class facilitates identifying neighboring positions for any given position, as well as comparing two positions to see if they are the same. Its methods are also summarized on page 141.

The main class in this problem is the Stack. It is used to store all positions that have been already visited in the search for a solution, as well as all positions that are candidates for backtracking when the current path leads to a dead end. Using a trace of the stack during a run of the program, or alternatively using the Debugger and single-stepping through the loop in this program, answer the following questions.

  1. What is the contents of the stack when the program first reaches position [3] [6] in this maze?
  2. When the program reaches square [3] [5], it has two choices for a next step. Why does it prefer to next visit square [3][6] rather than [4] [5]?
  3. What other positions does the program reach where there is more than one choice for a next step, and what are those choices? In what order will it consider these other choices during its search for a solution?
  4. Suppose the todo list were implemented as a Queue instead of a Stack (see discussion on the bottom of page 142), so that the todo.add and todo.remove methods were implemented as enqueue and dequeue operations rather than push and pop operations. How would this simple change in the program change your answer to the previous question?
  5. The program finds only a single solution to a maze. Describe generally what kinds of changes would be needed to make this program find all solutions to the maze (assuming that there may be more than one path from s to f in a given maze).

Part 2 - Evaluating Polish Expressions

A Polish expression is an alternative way of writing an ariithmetic expression that allows a simple left-right evaluation strategy, as well as the elimination of the need for parentheses and operator precedence. Polish expressions can be simply defined as follows:

A. Any number is a Polish expression.

Note that this definition is recursive. That is,we can build arbitrarily long Polish expressions from simpler ones by repeatedly applying this definition. Here are some examples, along with their ordinary (infix) interpretations on the right:

Polish Expression
Infix Interpretation
3 4 -
3 4 5 - -
3 4 - 5 -
3 4 5 6 7 - - - -
3 4 5 * +
35 17 40 9 - * + 7 -
3 - 4
3 - (4 - 5)
3 - 4 - 5
3 - (4 - (5 - (6 - 7)))
3 + 4 * 5
35 + 17 * (40 - 9) - 7

A number of observations follow from these examples. First, each Polish expression has only one interpretation in terms of the above definition. The second example, for instance, is a Polish expression only if 3 is identified as P1 in the definition, 4 5 - is identified as P2, and - is identified as op. Since part A of the definition allows 3 to be a Polish expression (that's the "base case"), and Part B can be used (recursively) to assure that the subexpression 4 5 - is a Polish expression, the definition allows that the entire expression 3 4 5 - - is a Polish expression.

The second observation that we note from these examples is that there is no need to consider operator precedence or use parentheses when writing a Polish expression. The Infix expressions for the third and fifth examples in this list illustrate this point. The third example uses the fact that equal-preedence operators (- and -) are evaluated from left to right, while the fifth uses the fact that adjacent operators with different precedence (+ and *) are evaluated in order of precedence (* before +).

The third and most important observation we can draw from these examples is that the evaluation of a Polish expression can take place in a single left-right scan, using the assistance of a stack to store operands and intermediate results. This is not possible for infix expressions, whose evaluation may require many scans forward and backward before it is fully evaluated (see the last example in the above list, for instance).

Here's how the evaluation works. The program should have a Stack S for holding operands and intermediate results and a String nextWord for holding the next operand or operator in the input. The following steps are repeated in a loop until the end of the expression is reached:

1. Read nextWord
2. If it is not an operator (it is a number), push it onto the Stack S.
3. If it is an operator op;
a. Pop the Stack S and let P2 = this value
b. Pop the Stack S and let P1 = this value
c. Compute the value of P1 op P2 and push the result onto the Stack S

If these steps are followed carefully, the stack S should contain the final value of the expression when the loop terminates.

Design and implement a program class called EvalPolish that will evaluate any Polish expression using this strategy. The file name for this program should be lab6yourname.java.

Part 3 - Recognize Erroneous Polish Expressions

Not all sequences of operators and operands are valid Polish expressions. For instance, if the number of operators is not exactly one less than the number of operands or else the operators are misplaced, the expression is not valid. Moreover, if any string in the expression is not either an operator or an operand, the evaluation cannot proceed.

  1. What input and stack situation would signal the presence of an expression with too few operators (such as the expression 3 4 5 + 6 -)?
  2. What input and stack situation would signal the presence of an expression with too many operators (such as the expression 3 4 5 + + + )?
  3. What input and stack situation would signal the presence of an expression with misplaced operators (such as the expression 3 4 + + 5 )?
  4. Discuss the specific changes that are needed in your program so that it can recognize an invalid Polish expression.
  5. (Optional) Make these changes in your program!

Lab 6 Deliverables:

Submit your Java program from Part 2 of this lab by dragging it to the Drop Box folder. Also hand in a hard copy listing of your program, along with your answers to the questions in Parts 1 and 3.

You may work on the programming parts of this lab in teams of two, but all answers to the questions should be developed individually.