/** Returns but does not remove an entry with minimum key. */
  public Entry min() throws EmptyPriorityQueueException {
    if (isEmpty()) 
      throw new EmptyPriorityQueueException("Priority queue is empty");
    return entry(T.root());
  }
  /** Inserts a key-value pair and return the entry created. */
  public Entry insert(Object k, Object x) throws InvalidKeyException {
    checkKey(k);  // may throw an InvalidKeyException
    Entry entry = new MyEntry(k,x);
    upHeap(T.add(entry));
    return entry;
  }
  /** Removes and returns an entry with minimum key. */
  public Entry removeMin() throws EmptyPriorityQueueException {
    if (isEmpty()) 
      throw new EmptyPriorityQueueException("Priority queue is empty");
    Entry min = entry(T.root());
    if (size() == 1)
      T.remove();
    else {
      T.replace(T.root(), T.remove());
      downHeap(T.root());
    }
    return min;
  }
  /** Returns the entry stored at a heap node. */
  protected Entry entry (Position p) { 
    return (Entry) p.element(); 
  }
  /** Returns the key stored at a heap node. */
  protected Object key (Position p) {
    return ((Entry) p.element()).key(); 
  }
  /** Determines whether a given key is valid. */
  protected void checkKey(Object key) throws InvalidKeyException {
    try {
      comp.compare(key,key);
    }
    catch(Exception e) {
      throw new InvalidKeyException("Invalid key");
    }
  }