/** helper search method */
  private int findItem(Object key) throws InvalidKeyException {
    check(key);
    int i = h.hashValue(key) % N; // division method compression map
    int j = i;
    do {
      if (empty(i))   return -1;  // item is not found
      if (available(i))   i = (i + 1) % N;  // bucket is deactivated
      else if (h.isEqualTo(key(i), key))  // we have found our item
        return i;
      else  // we must keep looking
        i = (i + 1) % N;
    } while (i != j);
    return -1;  // item is not found
  }
  // methods  of the dictionary ADT
  public Object findElement (Object key) throws InvalidKeyException {
    int i = findItem(key);  // helper method for finding a key
    if (i < 0) return Dictionary.NO_SUCH_KEY;
    return element(i);
  }
  public void insertItem (Object key, Object element) throws InvalidKeyException {
    check(key);
    int i = h.hashValue(key) % N;  // division method compression map
    int j = i;  // remember where we are starting
    do {
      if (empty(i) || available(i)) {  // this slot is available
        A[i] = new Item(key, element);
        n++;
        return;
      }
      i = (i + 1) % N;  // check next slot
    } while (i != j);  // repeat until we return to start
    throw new HashTableFullException("Hash table is full.");
  }
  public Object removeElement (Object key) throws InvalidKeyException {
    int i = findItem(key);  // find this key first
    if (i <0) return Dictionary.NO_SUCH_KEY;  // nothing to remove
    Object toReturn = element(i);
    A[i] = AVAILABLE; // mark this slot as deactivated
    n--;
    return toReturn;
  }