CS62 - Spring 2010 - Lecture 12

  • reversing a linked list
       - need 3 pointers
          - prev
          - current
          - next

  • recursive DFS
       - replace the while loop with recursion
       - also we won't need a queue anymore
       - what is the base case?
          - if we find a page that we've already visited, stop going down
          - a secondary base case when we reach a page without any links that haven't been visited
       - what's the recursive case
          - recurse on each of the neighbors of this page
       - need to pass along the visited list to keep track of it globally
       - look at dfsRecursive method in Search code
       - is the order going to be the same as the iterative DFS?
          - the order will be different
          - the stack implementation will go deeper starting at the last neighbor
          - the recursive implementation will go deeper starting at the first neighbor
       - why did the recursive depth first search look a lot like breadth first search?

  • maze problem

    ------------------ 
    |1   |       |   |
    ---- - -------- -- 
    |      |         |
    -- ---------- ---- 
    |    |           |
    --- -- ----- ----- 
    |       |        |
    -------- ---------
    |               0|
    ------------------
    

       - how can we pose this problem as a search problem?
          - for a search problem, we need some notion of a node and neighbors
             - node, is the position in the maze
             - neighbors are then non-wall adjacent cells
       - what would happen if we run BFS on this maze?
    ------------------
    |1***|       |   |
    ----*- -------- --
    |      |         | 
    -- ---------- ----
    |    |           | 
    --- -- ----- ----- 
    |      |        | 
    - ------ ---------
    |               0| 
    ------------------
    
    ------------------
    |1***|       |   | 
    ----*-* -------- --
    |******|         | 
    --*---------- ----
    |    |           |
    --- -- ----- ----- 
    |      |        | 
    - ------ ---------
    |               0| 
    ------------------
    
    ------------------
    |1***|*****  |   |
    ----*-*-------- --
    |******|         | 
    --*---------- ----
    |****|         | 
    ---*-- ----- ----- 
    | ***  |         | 
    - ------ ---------
    |               0| 
    ------------------
    

          - slowly branches out comparing all positions at distance X away from the starting point before moving on
       - what about DFS?
    ------------------
    |1***|       |   |
    ----*- -------- --
    |      |         |
    -- ---------- ----
    |    |           |
    --- -- ----- -----
    |      |         |
    - ------ ---------
    |               0|
    ------------------
    
    ------------------
    |1***|       |   |
    ----*- -------- --
    |****  |         |
    --*---------- ----
    |*** |           |
    ---*-- ----- -----
    |      |         |
    - ------ ---------
    |               0|
    ------------------
    
    ------------------
    |1***|       |   |
    ----*- -------- --
    |****  |         |
    --*---------- ----
    |***  |          |
    ---*-- ----- -----
    |***   |         |
    -*------ ---------
    |***            0|
    ------------------
    

          - always going to try and go deeper. Similar to following one wall (in the example above, the right wall)
       - which is better?
          - DFS will probably find the exit faster
             - when is DFS slower?
          - BFS will find THE shortest path from the start to the finish
             - at each step it examines all paths that are one step further, so when it finds the exit, we know there are no shorter paths
             - proof
                - starting at node s, prove that when we get to t, that is a shortest path from s to t
                - assume a shorter path exists that was not found by BFS from s to t
                - Consider some u that the algorithm “misses” along the shortest path
                - Choose any path from s to u and look at the last vertex on that path that we
    actually visited
                - Call this node z
                - let w be the node immediately after it on the same path. z would be visited
    and w was not, which is a contradiction
    above.

  • chess
       - how can we view chess as a search problem?
       - ply
       - deep blue
          - 200 million positions per second
          - average of 6-8 moves ahead with the capacity for 20 or more
          - specialized hardware
          - vs. Kasparav (1996)
       - deep fritz
          - normal hardware
          - 8 million positions per second
          - 17-18 moves ahead
       - what about other games?

  • postfix notation (aka reverse polish notation)
       - what we normally think of as algebraic notation is called infix notation
          - the operators are in between the operands
             - 2 + 2
             - (1 + 3) * 4
       - postfix notation puts the operator at the end of the arguments, that is operators follow the operands
          - 3 4 +
          - 2 5 *
       - we can make more complex expression
          - (2 + 4) * 5
             - 2 4 + 5 *
          - (4 - 1) * (3 + 5)
             - 4 1 - 3 5 + *
          - notice that we no longer need parenthesis since there is no ambiguity
       - the algorithm to handle postfix notation is as follows:
          - Read the next token from input
          - If the token is a value
             - push it onto the stack
          - Otherwise, the token is an operator
             - It is known a priori that the operator takes n arguments
             - If there are fewer than n values on the stack
                - (Error) The user has not input sufficient values in the expression
             - Else, Pop the top n values from the stack
             - Evaluate the operator, with the values as arguments
             - Push the returned results, if any, back onto the stack
       - try a few:
          - 1 2 3 4 5 6 * + - / +
          - 2 3 + 5 * 2 2 2 * * +
          - 1 2 + 8 3 * -
          - 7 6 5 + 1 + + +
       - converting from infix to postfix
          - 5 + ((1 + 2) * 4) − 3
             - 1 2 + 4 * 5 + 3 -
             - 5 1 2 + 4 * 3 -
          - ((9 - 4) * 5)/2 + 4 * 5
             - 9 4 - 5 * 2 / 4 5 * +
             - 4 5 * 2 5 9 4 - * / +
          - many different ways to do it!
       - prefix notation is the reverse of postfix notation
          - + 2 3
          - + - 2 3 4

  • ActionListener interface (http://java.sun.com/j2se/1.5.0/docs/api/java/awt/event/ActionListener.html)
       - Listeners are a way for your program to respond to events (often generated by the user)
       - ActionListener listens for actions performed by the user
       - show SimpleActionListener demo
          - two different buttons
          - when we click on the button, the message changes
       - To implement a new ActionListener
          - import java.awt.event.*;
          - implements ActionListener
             - must implement:
             public void actionPerformed(ActionEvent e)
          - the actionPerformed method is called every time a user generated action is performed on an object you were "listening to"
          - information about which object it was and other details is passed in the ActionEvent parameter
       - Once you have a class that implements ActionListener, you need to :
          - create a new object of that class, say myListener
          - call "addActionListener" and pass in your object (myListener) on any objects that you'd like to have your class respond to action events, for example, button clicks
       - show SimpleActionListener code
          - often it's simple to have the ActionListener and the class generating the events (e.g. from buttons) be the same class
          - register both of the buttons using ".addActionListener(this"
          - in the actionPerformed method
             - just need to check to see which button caused the addActionPerformed method to be called and act accordingly
       - we can also have listeners that are by themselves listeners
          - look at ExernalActionListener class in SimpleActionListener code
             - this class does not implement ActionListener
             - however, the ButtonActionListener class does
                - we create a new ButtonActionListener
                - and tell the buttons that that object/class will handle the action events
          - look at ButtonActionListener class in SimpleActionListener code
             - this class does implement ActionListener
             - and then makes the appropriate changes
             - why do we need to have ExternalActionListener passed in the constructor?
                - in response to the clicks, we need to make changes to objects that part of the object/class