import java.io.*; /************************************************************************** /* Programmer: Sriram Pemmaraju /* Date: Oct 7th, 2007 /* Depends on the StringLink and the StringLinkList classes /**************************************************************************/ class Dictionary{ private StringLinkList[] table; // stores the hash table as an array of // singly linked lists private int M; // size of hash table private int numWords; // number of words in hash table // computes the hash function of a given string. Assumes // that the string consists of lower case letters. Views // the string as a base-32 number and returns equivalent // decimal value modulo 32. Uses bit shifting for multiplying // by 32 and Horner's rule for reducing number of multiplications private int hash(String word) { int hashValue = 0; for(int i = 0; i < word.length(); i++) hashValue = ((hashValue << 5) + (word.charAt(i)-'a')) % M; return hashValue; } // Constructs a Dictionary of the given size public Dictionary(int size) { M = size; table = new StringLinkList[M]; numWords = 0; // Initialize all linked lists in the hash table to // empty for(int i = 0; i < M; i++) table[i] = new StringLinkList(); } // Searches for the given String myWord. Returns // null if not found; otherwise, returns a copy of the Link // containing the String public StringLink search(String myWord) { // compute the hash value of the given word int index = hash(myWord); // need to call the search/find function in the LinkList class StringLink myLink = table[index].find(myWord); // Either return null or a copy of the Link that was found if(myLink == null) return null; else return new StringLink(myLink.sData, null); } // Inserts the given String. Does not search first public void insert(String myWord) { int index = hash(myWord); table[index].insertFirst(myWord); numWords++; } // Deletes a Record with the given word public void delete(String myWord) { // compute the hash value of the given word int index = hash(myWord); // need to call the delete function in the LinkList class StringLink myLink = table[index].delete(myWord); if(myLink != null) numWords--; } // Returns the number of words in the hash table public int numberWords() { return numWords; } // Prints the contents of the hash table by printing // contents of each non-empty linked list in the hash table public void print() { for(int i = 0; i < M; i++) table[i].displayList(); } public void printStatistics() { System.out.println("Number of words is: "+ numWords); System.out.println("Here is how the words are distributed:"); int max = 0; for(int i = 0; i < M; i++) if(table[i].size() > max) max = table[i].size(); System.out.println("Max length is: "+ max); int[] distribution = new int[max+1]; for(int i = 0; i < distribution.length; i++) distribution[i] = 0; for(int i = 0; i < M; i++) distribution[table[i].size()]++; System.out.println("Length Number of words"); for(int i = 0; i < distribution.length; i++) System.out.println(i+"\t "+distribution[i]); } // The main method tests the class by inserting into a Dictionary object the // 5757 words from words.dat. public static void main(String args[]) { // I wanted to make the load factor about 1/5 by choosing a // hash table size about 5 times the number of words that the // table is supposed to hold. There are 5757 words in words.dat. // 5757*5 = 28785 and the next smallest prime is 28789. Prime numbers // are sometimes chosen as hash table sizes because they tend to reduce // collisions. Dictionary D = new Dictionary(28789); try { // This is one way to read from a file. The list of all 5-letter words // is in a file called words.dat BufferedReader in = new BufferedReader(new FileReader("words.dat")); String word; // read all the words from the file System.out.println( "Reading words.dat..." ); while( (word = in.readLine()) != null ) // Insert the word into the Dictionary D.insert( word ); in.close(); D.printStatistics(); } catch (IOException e) {} } // end of main } // end of class