public Position first()				// O(1) time
      throws EmptyContainerException {
    if (isEmpty())
      throw new EmptyContainerException("List is empty");
    return header.getNext();
  }
  public Position last()				// O(1) time
      throws EmptyContainerException {
    if (isEmpty())
      throw new EmptyContainerException("List is empty");
    return trailer.getPrev();
  }
  public Position before(Position p)			// O(1) time
      throws InvalidPositionException, BoundaryViolationException {
    DNode v = checkPosition(p);
    DNode prev = v.getPrev();
    if (prev == header)
      throw new BoundaryViolationException
	("Cannot advance past the beginning of the list");
    return prev;
  }
  public Position insertBefore(Position p, Object element) 
      throws InvalidPositionException {			// O(1) time
    DNode v = checkPosition(p);
    numElts++;
    DNode newNode = new DNode(v.getPrev(), v, element);
    v.getPrev().setNext(newNode);
    v.setPrev(newNode);
    return newNode;
  }
  public Position insertFirst(Object element) {		// O(1) time
    numElts++;
    DNode newNode = new DNode(header, header.getNext(), element);
    header.getNext().setPrev(newNode);
    header.setNext(newNode);
    return newNode;
  }