Title: Computer Science 187
1Computer Science 187
Introduction to Programming with Data Structures
Lecture 11 Stacks and Mazes
Announcements
- Midterm exam October 29 in class
- A new OWL assignment is up, due 10/20.
- Help for studying for the midterm is available
- on the WIKI.
2Implementing Stacks
- Book shows four possibilities
- As an extension to Vector
- With a list component
- Using an array
- As a linked structure
- Included in these notes but not covered in class
- Book defines a stack interface on page 259 Java
has no stack interface
3Implementing Stack as Extension of Vector
- Collection hierarchy includes java.util.Stack
- The Vector class offers a growable array of
objects - Elements of a Vector accessed by index
- Size can grow or shrink as needed
- That is Vector is just like ArrayList
4Implementing Stack as Extension of Vector (2)
Top element of the Stack is at the highest index
5Stack Code
- public class StackltEgt extends VectorltEgt
- public E push (E e)
- add(e)
- return e
-
- public E pop () throws EmptyStackException
- try
- return remove(size()-1)
- catch (ArrayIndexOutOfBoundsException ex)
- throw new EmptyStackException()
-
-
- ...
6Stack Code (2)
- public class StackltEgt extends VectorltEgt
- ...
- public E peek () throws EmptyStackException
- try
- return get(size()-1)
- catch (ArrayIndexOutOfBoundsException ex)
- throw new EmptyStackException()
-
-
- public boolean empty ()
- return size() 0
-
7Implementing Stack with a List
- Can use ArrayList, Vector, or LinkedList
- All implement the List interface
- Name of class illustrated in text is ListStack
- ListStack is an adapter class
- Adapts methods of another class to ...
- Gives different names to essentially the same
operations
8ListStack Code
- public class ListStackltEgt
- implements StackIntltEgt
- private ListltEgt list
- public ListStack ()
- list new ArrayListltEgt()
- // or new VectorltEgt or new LinkedListltEgt
-
- public E push (E e)
- list.add(e)
- return e
-
- ...
9ListStack Code (2)
- public E peek ()
- if (empty())
- throw new EmptyStackException()
- return list.get(list.size()-1)
-
- public E pop ()
- if (empty())
- throw new EmptyStackException()
- return list.remove(list.size()-1)
-
- public boolean empty ()
- return list.size() 0
10Implementing Stack Using an Array
- Must allocate array with some default capacity
- Need to keep track of the top of the stack
- Have no size method, so must track size
- Similar to growable PhoneDirectory
- Why not just use vector?
11Implementing Stack Using an Array (2)
12ArrayStack Code
- public class ArrayStackltEgt
- implements StackIntltEgt
- private static final int INITIAL_CAPACITY 10
- private E data
- (E) new ObjectINITIAL_CAPACITY
- private int top -1
- public ArrayStack ()
- public boolean empty () return top lt 0
- ...
13ArrayStack Code (2)
- public E push (E e)
- if (top data.length) reallocate()
- return datatop e
-
- public E pop ()
- if (empty()) throw new EmptyStackException()
- return datatop--
-
- public E peek ()
- if (empty()) throw new EmptyStackException()
- return datatop
14ArrayStack Code (3)
- private void reallocate ()
- E newData (E) new Objectdata.length2
- System.arraycopy(data, 0, newData, 0,
- data.length)
- data newData
-
15Implementing Stack as a Linked Structure
- We can implement Stack using a linked list
16LinkedStack Code
- public class LinkedStackltEgt
- implements StackIntltEgt
- private NodeltEgt top null
- public LinkedStack ()
- public boolean empty () return top null
- public E push (E e)
- top new NodeltEgt(e, top)
- return e
-
- ...
17LinkedStack Code (2)
- public E pop ()
- if (empty()) throw new EmptyStackException()
- E result top.data
- top top.next
- return result
-
- public E peek ()
- if (empty()) throw new EmptyStackException()
- return top.data
-
18LinkedStack Code (3)
- private static class NodeltEgt
- private E data
- private NodeltEgt next
- Node (E data, NodeltEgt next)
- this.data data
- this.next next
-
19Comparison of Stack Implementations
- Vector is a poor choice exposes Vector methods
- Likewise, extending other List classes exposes
their methods - Using a List as a component avoids exposing
- LinkedStack operations are O(1)
- But Node objects add space overhead
- ArrayList component is perhaps easiest
- Still some space overhead (StackArrayList)
- Array as a component best in space and time
- But somewhat harder to implement
20(No Transcript)
21M. C. Escher Relativity
22Isabelle de Beaufort's environmental maze in the
village of reignac sur Indre in
France. http//cccw.adh.bton.ac.uk/schoolofdesign/
MA.COURSE/LMaze.html
23An Application of Stacks Solving a Maze
- Mazes and Labyrinths whats the difference?
Enter
Exit
http//www.astrolog.org/labyrnth
24The Palace at Knossos
Greek myth of Thesesus and the Minotaur.
http//www.unmuseum.org/maze.htm
25Whats a Plausible Approach to Solving a Maze?
Exit
Enter
26Solving a Maze
- Represent as an array with black and white spaces
Path
Important decision / choice points which path
to follow?
Wall
Dead-ends
No-brainers
Special
27The General Cases
North
- What direction can we move in?
- not walls
- not back where we came from
West
East
South
Choice
N E S W 1 0 1 1
U
(choice)
0
U
Dead-End
No-Brainer
N E S W 0 0 0 1
(deadend)
(no choice)
allowed directions
0
0
28What to do in each of the cases?
- No-Brainer Case
- only one direction that we can move in.
- suppose I know my current location and the
direction to move? - I want to take a step .whats my next
coordinates?
U
29What to do in each of the cases?
- The choice or decision case
- need to remember all possibilities push each
onto a stack - need to choose one pop top one off the stack
- need to take a step in that direction
Helper Method
location direction
location direction
location direction
location direction
location direction
N E S W 1 0 1 0
U
location direction
POP
possible next steps
30What to do in each of the cases?
- Dead-end case
- need to go back to previous choice point and
explore an alternative path BACKTRACKING - if there are NO previous choice points, then
there is no path through the maze!
Wheres the next alternative(s) from the previous
choice point?? ON THE TOP OF THE STACK.
location direction
location direction
POP
Becomes new location and direction
31Putting it all together
Helper Methods
- Given current location (start) and goal
location - Move one step into maze
- get current direction given starting location
- step in that direction
- Repeat forever
- v Is current location the goal? if yes,
report it found and stop. - v Get the allowed directions from here.
- v Handle the cases
- Only one choice.
- get direction to go in
- step in that direction
- More than one choice
- push a decision point onto the stack for EACH
possible direction - pop the top location and set current location and
direction accordingly - take a step in that direction
- No choices (dead-end)
- If the stack is not empty, get top element (pop),
set current location and direction, and step in
that direction - If the stack IS empty, report failure and stop.
32The Maze Program Classes Used
- All the stack classes
- LinkedStack.java,
- StackfullException.java, StackEmptyException.java,
- Node.java, Stack.java
- The interface defining compass directions
- CardinalDirections.java
-
- int NORTH 0 int EAST 1 int SOUTH 2 int
WEST 3 - The class defining a location
- Location.java protected int row protected int
col - The class defining the structure of the
information pushed onto the stack - decBlock.java myLocation currPos
myDirmyDirection - The class defining the maze itself
- Maze.java
- A test program
- TestMaze.java reads in maze, prints it, and
solves it,
33A Maze in a File
The size of the maze (rows, columns)
- 5 5
- 2 0
- 3 4
- .
-
- ..
- ...
- ....
The starting square (row, col)
The goal square
The symbol used for wall and path
The maze itself
34Maze.java
- public class Maze implements CardinalDirections
- protected char maze //the maze upper
left corner of maze is (0,0) - protected int nrows, ncols //size of maze
- protected location start //(row,col)
coordinates of starting point - protected location goal //(row,col) coordinates
of goal (i.e. the exit from the maze) - protected char wallSym //symbol used in file to
designate a wall - protected char pathSym //symbol used in file to
designate a path - protected boolean debug //debug flag...if true,
debugging statements are on - private int currDir //my current direction
North0, East1, etc. - private location currLoc //my current location
in the maze (location is a row and column) - private int allowed //array of four possible
directions I can move in from my - //current location with 0 indicating I can't go
that way, and 1 indicating - //I can in order NESW
-
- private LinkedStack choices //the stack to be
used in the method mazeSolve() -
- private BufferedReader B //reader for maze file
- private String fname //file that the maze
is on
35The public methods of Java.maze
- public Maze(String fileName, boolean IsDebugOn)
throws IOException - sets up a buffered reader for the maze file
- reads the array size, start location, goal
location, and symbols from file - creates the maze array
- creates the choices stack
- public char getMaze()
- get method which returns the two dimensional
maze array - public void readMaze() throws IOException
- reads the maze array itself from the file and
fills maze array - public void writeMaze ()
- prints the maze
- public boolean mazeSolve()
- returns true if the maze has a path from start to
goal and false otherwise - public void closeFile() throws IOException
- closes the maze file and frees I/O resources
36The private methods of Maze.Java
- private char toChar(String s)
- returns the character equivalent of the first
element of s - private int getDirection()
- returns the direction corresponding to location
of first allowed direction in the allowed
direction vector - private void step ()
- given a direction, moves us to the next maze
square in that direction by modifying the current
location - private int getStartDir()
- given the starting location, determine the
direction to step into the maze - private boolean isGoal()
- compares current location and goal location
returns true if they match - private void getAllowed()
- returns the four element vector indicating
whether or not (1 or 0) we can move in the
corresponding direction from the current location - private void updateStack()
- for every allowed direction from the current
location, pushes a location block onto the stack.
Each block contains the current location and a
direction to move in.
37The mazeSolve method
- public boolean mazeSolve()
- currDir getStartDir() //get direction
to go in to step into the maze - step()
//step into it -
- while (true)
-
- if(isGoal()) return true //weve
found a solution, so were done. - getAllowed() //where can
I go from here? - int sumsumAllowed() //add up the
elements of the allowed vector -
- switch(sum)
- case 0
//We have nowhere to go from this square
(deadend) -
- if( !choices.isEmpty()) //Go back
to previous decision point- search from there. -
- decBlock old (decBlock)
choices.pop() - currLoc old.decLocation
//update our location and direction - currDir old.myDir
- step()
38Maze.java, continued
- case 1 //We
have only one direction I can go in, so do it. - currDirgetDirection()
- step()
- break
-
-
- default
//We have more than one direction to go in. -
- updateStack() //push a
block for each alternative (save them) - decBlock old (decBlock)
choices.pop() //get one of the ones just
pushed -
//and start
exploring. - currLoc old.decLocation
- currDir old.myDir
- step()
- break
-
- //end switch
- // end while
39A Test Program
- import java.io.
- public class test_Maze
- public static void main(String args) throws
IOException -
- boolean debug
- String strnull
- String fileName args0
- try
- str args1
- catch (ArrayIndexOutOfBoundsException e)
- str"false"
-
- if (str.equalsIgnoreCase("true"))
- debugtrue
- else debugfalse
40Test Program The Important Part
-
- Maze mazer new Maze(fileName, debug)
-
- mazer.readMaze() // read
the Maze - mazer.closeFile() //close
out the input file - mazer.writeMaze() //write
the maze to the console - if (mazer.mazeSolve()) //solve the
maze - System.out.println("This maze HAS a
solution") - else
- System.out.println("This maze DOES NOT
HAVE a solution") -
41Results
- -------------Reading Maze from filemaze12x12.txt-
------- - Size 12 rows by 12 columns.
- Start location for maze 2, 0
- Goal location for maze 10, 11
- is used to designate a wall
- . is used to designate a path
- ---------------------Finished Reading-------------
------- - -------Printing maze of size 12 rows by 12
columns------- -
- ..........
- ..
- ........
- ..
- ..........
- .
- .........
- ...
- .........
- ..
42No Results
- --------Reading Maze from filemaze12x12_noexit.tx
t---------- - Size 12 rows by 12 columns.
- Start location for maze 2, 0
- Goal location for maze 10, 11
- is used to designate a wall
- . is used to designate a path
- ---------------------Finished Reading-------------
---------- - ---------Printing maze of size 12 rows by 12
columns-------- -
- ..........
- ..
- ........
- ..
- ..........
- .
- .........
- ...
- ........
- ..
Change from previous example.