Sample Final

This sample final contains the kinds of questions that will be on the actual final. It is much longer than the final will be. At least one question on the final will be all but identical to one here. The final is comprehensive: at least one question will come from the first half of the course. See the sample midterm for examples of such questions.

We will not post solutions to the sample final problems because, in our experience, people will be tempted to look at the solution before completely doing the problem. If anyone wishes to check their answers, they may give us a paper copy for review.

Definitions and Motivation

Reading Code

Read the solutions to Homeworks 1-14 and answer the following questions:

  1. Homework #1
    1. Why should move() never call paintContents? What could happen wrong if we did so?
    2. Why should paintContents() never call move() ? What could happen wrong if we did so?
    3. Why does Location not define a setX method?

  2. Homework #2
    1. What is the connection (if any) between _data.length and _manyItems ?
    2. Why does DiskSeq.append call ensureCapacity every time it is called? Isn't that inefficient?
    3. Why does remove require a for-loop ?
    4. Why do we throw an exception in parseString has an error? Why not simply print an error message?

  3. Homework #3
    1. Why do we show an error message if parseInt throws an exception? Why don't we just fix our bug?
    2. What is the difference between _done and _stopped ? Can we be done when we're not stopped (still moving) ? Can we be stopped if we're not done?
    3. In CarControlSeq, why does the iterator function return this ? (Why not make it a void method?)

  4. Homework #4
    1. Why does _wellFormed count up the nodes rather than just calling size() ?
    2. The invariant checker checks whether precursor is null or in the list. What would it mean to be non-null and not be in the list? How could that happen?
    3. appendAll has an empty for-loop in it. What's the point?
    4. And why does it call clone ?
    5. What does it mean for cursor to be null? (See, e.g. hasNext().)

  5. Homework #5
    1. What about the code means that a triangle can be in only on Group at a time?
    2. What is the purpose of the Key interface? Why does it not include any code?
    3. How many keys are used in the program? Can you think of any other possible keys?
    4. removeFirst includes a condition in which along one branch, two pointers are assigned and in the other only one pointer is assigned. This is usually the sign of a bug. Why not in this case? (What is the missing assignment?)
    5. In sortForward, we have the condition:
      if (p != t._prev)
      
      What does this condition refer to? What would be true if the two pointers were equal?
    6. How can sortForward be very efficient even if started at the front? (It has two nested while loops.)

  6. Homework #6
    1. cursor is a ``ghost field.'' What does that mean?
    2. How does hasNext get its value? How does next() set its value?
    3. appendAll special cases the empty addend. Would the rest of the code work properly for this case? Explain!
    4. The dummy node is supposed to make the coding easier. How would append have to be more complex, if we didn't have a dummy node?
    5. In clone() why is it necesary to change answer.precursor ?

  7. Homework #7
    1. How do we avoid ever having null pointers in the list? Why is that desirable?
    2. How is the dummy node created to point to itself?
    3. In add, we have the line:
      _tail = _tail.next = new Node<T>(x,_tail.next);
      
      Why don't we simply say _tail = new Node(...). Would there be any difference?
    4. Why do we override the clear() method.
    5. What does LinkedList.this._wellFormed() in the iterator code mean?
    6. How does next() ensure you don't go around in cycles forever?
    7. In MyIterator.remove there is the line:
      _myVersion = ++_version;
      
      What does this line do? (It does two things!) If this line were omitted, what problem would result? What if it simply said ++version ?

  8. Homework #8
    1. Why does ensureCapacity need both i and j when copying elements from one array to another?
    2. Why does offer rejecr null? Would anything go bad if it accepted null?
    3. Why doesn't poll shift all the remaining elements over?
    4. Why does clear allocate a new array?
    5. In the following code:
      if (++k >= _data.length) k = 0;
      _data[j] = _data[k];
      
    We shift k if it falls off the end, but not j. Why not? What is the relation between j and k ?

  9. Homework #9
    1. What purpose does _checkInRange have? Why something so complicated?
    2. Why doesn't add permit two listings to have the same price? What would happen if a different listing (different addresses) with the same price was added?
    3. In remove, there is a second while loop:
      while (t.left != null) {
        lag = t;
        t = t.left;
      }
      
      What is this loop doing? Why?
    4. In addAll, the solution gives both efficient and inefficient code. What is inefficient about the (much cleaner looking) ``inefficient code'' ?
    5. Explain the syntax of the following line and describe why it is doing what it does:
      int n1 = add(array[mid]) ? 1 : 0;
      

  10. Homework #10
    1. In the iterator, what does the stack of _pending nodes represent?
    2. In hasNext there are three separate cases. Indicate what state the system is in (in terms of the client) that these three cases refer to.
    3. It seems that next() has duplicated code (two similar or even identical while loops). Could the last two cases of next() be combined?
    4. What is happening on the line of remove() marked ``overwrite'' ? Explain!

  11. Homework #11
    1. Why do we have dummy listings in the table? When do they show up? When do they go away?
    2. The invariant includes the following code:
      if (h > i) {
        if (h <= lastNull || lastNull < i ) return _report(...)
      } else {
        if (h <= lastNull && lastNull < i) return _report(...)
      }
      
      Draw pictures to explain what these conditions mean.
    3. The rehash method may descrease the size of the array. When does that happen?
    4. In several methods, we have lines similar to:
      ++h;
      if (h == _contents.length) h = 0;
      
      What is going on? Why?
    5. In add, we have the following condition:
      if (l2 == dummyListing) {
        if (place == -1) place = h;
      }
      
      What is that code doing? Explain!
    6. Why does put sometimes increment _numListings, sometimes _numUsed, sometimes neither (returning early), but never _numUsed by itself? What do these three cases represent?

  12. Homework #12
    1. Why is _ropen a different size than _copen?
    2. read says it may throw an IOException but in the code, it only throws ParseException. Why is this accepted by the compiler. If we changed IOException in the method header to ParseException, the code would not compile any more. Why not?
    3. How does findPath know if it has reached the goal?
    4. The method findPath ensures that the stack always includes a path. How does it ever consider an alternate route from a node? Why? What would happen if we didn't do that?
    5. In the drawing code, we have the following condition:
      if (_marked[_rows-1][0]) {
        g.fillRect(0, (2*_rows-1)*SQUARESIZE, SQUARESIZE, 2*SQUARESIZE);
        g.fillRect((2*_columns-1)*SQUARESIZE, 0,2*SQUARESIZE, SQUARESIZE);
      }
      
      What is this code doing? Why is there a condition?

  13. Homework #13
    1. Why does Icon inherit from CenteredShape ? Why not Polygon or Triangle ?
    2. Why does Trianglke inherit from Polygon when Rectangle does not?
    3. Why is CenteredShape abstract whereas Polygon is not?
    4. Why does the constructor for Disk not initialize the radius attribute?
    5. What does Point... mean?

  14. Homework #14 (TBA)

Please answer the following questions about this code:

  1. Why is the constructor doing lots of work, not just starting at the root?
  2. What is the distinction between previous and next ? Why do we return previous.data at the end of next(), not the more reasonable next.data ?
  3. What does the condition next.right == null signify about the iterator with respect to the tree rooted at ``next.''?
  4. Why does the first branch go up one more time after the while loop is done?
  5. If next.parent is null in the while loop of the first branch, what does that mean?
  6. The right branch does something very similar to what elsewhere in this code? Why?
Read the following code that finds a path by search through a directed graph:

  private Set<Node> visited = new HashSet<Node>();

  /**
   * Initialize for a new search
   */
  protected abstract void init();

  /**
   * Add a search state to be considered later
   * @param s search state to add.
   */
  protected abstract void add(SearchState s);

  /**
   * Are there any more search states to consider?
   * @return whether there are any more search states
   */
  protected abstract boolean hasNext();

  /**
   * Return next search state to consider
   * @return
   */
  protected abstract SearchState next();

  public SearchState find(Node from, Node to) {
    visited.clear();

    init();
    add(new SearchState(from));

    while (hasNext()) {
      SearchState s = next();
      Node last = s.last();
      if (last == to) {
        return s;
      } else if (!visited.contains(last)) {
        visited.add(last);
        for (Edge edge : last.edges()) {
          add(s.extend(edge));
        }
      }
    }

    return null;
  }
...
  public class SearchState implements Iterable<Edge> {
    private Node initial;
    private List<Edge> path;

    public SearchState(Node i) {
      initial = i;
      path = new ArrayList<Edge>();
    }

    public Node first() {
      return initial;
    }

    public Iterator<Edge> iterator() {
      return path.iterator();
    }

    /**
     * Return the last node on this path.
     * If the path is empty, we're still in the initial node.
     * @return last node on path
     */
    public Node last() {
      ...
    }

    /**
     * Return a new search state which is like this one except
     * with a path extended by the given edge.
     * @param e edge to add to new state's path.
     * @return new search state.
     */
    public SearchState extend(Edge e) {
      ...
    }
  }
}

  1. What role does visited play? What would happen if we moved the call to clear the visited set into the ``while'' loop?

  2. How should add and next be implemented to achieve depth-first search? breadth-first search? Why?

Code

Debugging

About this document



John Tang Boyland 2011-05-13