import Dictionary; import Entry; /** * Hash tables that use the "shift into an empty space" strategy. * * @author Herman Hacker * @author Hermione Hacker * @author Thelma Thinker * @author Thomas Thinker * @author Samuel A. Rebelsky * @version 1.1 of April 2000 */ public class ShiftyHashTable implements Dictionary { // +--------+---------------------------------------- // | Fields | // +--------+ /** * An array that contains all the elements in the * hash table. An entry might be stored at location * entry.getKey().hashCode() % entries.length * (or after, if that cell is full). If null is stored * in a particular cell, that cell is empty. */ protected Entry[] entries; /** * The number of entries in the hash table. Not * the same as entries.length, since some (hopefully * many) of the cells in entries will be null. */ protected int numEntries; /** * The last place the findKey operation looked. Useful * for the add routine. */ protected int curLoc; // +--------------+---------------------------------- // | Constructors | // +--------------+ /** * Build a new hash table that should work relatively * well for up to maxEntries entries. */ public ShiftyHashTable(int maxEntries) { this.numEntries = 0; this.entries = new Entry[maxEntries*2]; } // ShiftyHashTable(int) // +------------+------------------------------------ // | Extractors | // +------------+ /** * Determine if a particular key is in the dictionary. */ public boolean contains(Object key) { // Find the key. try { findKey(key); return true; } // If the key wasn't there, return false. catch (Exception e) { return false; } } // contains(Object) /** * Look up an entry in the dictionary. */ public Object lookup(Object key) throws Exception { // Find the index for the key and return the // corresponding entry. Since findKey throws // an exception if the key is not found, we don't // need to. return entries[findKey(key)].getValue(); } // lookup(Object) // +-----------+------------------------------------- // | Modifiers | // +-----------+ /** * Add an entry to the dictionary. */ public void add(Object key, Object value) throws Exception { try { findKey(key); // Hmm ... it's there. Can't re-add. throw new Exception("Already there"); } catch (Exception e) { // It's not there. Use curLoc. if (entries[curLoc] == null) { ++numEntries; entries[curLoc] = new Entry(key,value); } else { throw new Exception("No room"); } } // catch (Exception) } // add(Object, Object) /** * Delete an entry in the dictionary. */ public void delete(Object key) throws Exception { throw new Exception("STUB"); } // delete(Object) // +---------+--------------------------------------- // | Helpers | // +---------+ /** * Determine the index of a particular key. * @exception Exception * If the key is not in the table. */ protected int findKey(Object key) throws Exception { // Determine the first place to look. int startLoc = key.hashCode() % entries.length; curLoc = startLoc; // Step through until we (1) find the desired // key; (2) find an empty space; or (3) return // to where we started. do { // Is there no entry at the appropriate index? if (entries[curLoc] == null) { throw new Exception("Not found"); } // Is an equal entry at the appropriate index? if (key.equals(entries[curLoc].getKey())) { return curLoc; } // Advance to the next index. curLoc = (curLoc + 1) % entries.length; } while (curLoc != startLoc); // We've wrapped around or hit null. Give up. throw new Exception("Not found"); } // findKey(Object) } // class ShiftyHashTable