240 likes | 257 Views
Podcast Ch21c. Title : Hash Table Implementation Description : Overview of implementation; load factors; add() method; rehash() method; remove() method Participants : Barry Kurtz (instructor); John Helfert and Tobie Williams (students)
E N D
Podcast Ch21c • Title: Hash Table Implementation • Description: Overview of implementation; load factors; add() method; rehash() method; remove() method • Participants: Barry Kurtz (instructor); John Helfert and Tobie Williams (students) • Textbook: Data Structures for Java; William H. Ford and William R. Topp
A Hash Table as a Collection • The generic class Hash stores elementsin a hash table using chaining with separate lists and implements the Collection interface. • hashCode() must be provided by the generic type. • The constructor creates a hash table with initial size 17. The table grows as rehashing occurs. • The method toString() returns a comma-separated list that, by the nature of hashing, is not ordered.
Hash Class Implementation • The hash table is an array whoseelements are the first node in a singly linked list. • Define an inner class Entry with an integer field hashValue that stores the hash code value and avoids recomputing the hash function during rehashing. hashValue = item.hashCode() & Integer.MAX_VALUE;
Entry Inner Class private static class Entry<T> { // value in the hash table T value; // save value.hashCode() & Integer.MAX_VALUE int hashValue; // next entry in the linked list // of colliding values Entry<T> next; // entry with given data and node value Entry(T value, int hashValue, Entry<T> next) { this.value = value; this.hashValue = hashValue; this.next = next; } }
Hash Class Instance Variables • The Entry array, table, defines thesingly-linked lists that store the elements. • The integer variable hashTableSize specifies the number of entries in the table. • The variable tableThreshold has the value(int)(table.length * MAX_LOAD_FACTOR)where the double constant MAX_LOAD_FACTOR specifies the maximum allowed ratio of the elements in the table and the table size.
Hash Class Instance Variables (concluded) • MAX_LOAD_FACTOR = 0.75 (number of hash table entries is 75% of the table size) is generally a good value. When the number of elements in the table equals tableThreshold, a rehash occurs. • The variable modCount is used by iterators to determine whether external updates may have invalidated the scan.
Hash Class Constructor • The Hash class constructor creates the17-element array table with 17 empty lists. A rehash will first occur when the hash collection size equals 12.
Hash Class Outline public class Hash<T> implements Collection<T> { // the hash table private Entry[] table; private int hashTableSize; private final double MAX_LOAD_FACTOR = .75; private int tableThreshold; // for iterator consistency checks private int modCount = 0; // construct an empty hash table with 17 buckets public Hash() { table = new Entry[17]; hashTableSize = 0; tableThreshold = (int)(table.length * MAX_LOAD_FACTOR); } . . . }
Hash Class add() • The algorithm for add(): • Compute the hash index for the parameter item and scan the list to see if item is currently in the hash table. If so, return false. • Create a new Entry with value item and insert it at the front of the list. • hashValue is assigned to the entry so it will not have to be computed when rehashing occurs.
Hash Class add() (continued) • Increment hashTableSize and modCount. If hashTableSize ≥ tableThreshold, call rehash(). The size of the new table is 2*table.length + 1
Hash add() (continued) // add item to the hash table if it is not // already present and return true; otherwise, // return false public boolean add(T item) { // compute the hash table index int hashValue = item.hashCode() & Integer.MAX_VALUE, index = hashValue % table.length; Entry<T> entry; // entry references the front of a linked // list of colliding values entry = table[index];
Hash add() (continued) // scan the linked list and return false // if item is in list while (entry != null) { if (entry.value.equals(item)) return false; entry = entry.next; } // we will add item, so increment modCount modCount++; // create the new table entry so its successor // is the current head of the list entry = new Entry<T>(item, hashValue, (Entry<T>)table[index]);
Hash add() (concluded) // add it at the front of the linked list // and increment the size of the hash table table[index] = entry; hashTableSize++; if (hashTableSize >= tableThreshold) rehash(2*table.length + 1); // a new entry is added return true; }
If a hash table with n elements uses chaining with separate lists, what are the average and worst-case complexities for a successful and an unsuccessful search? Worst-case for a search: O (___ n ____) Worst-case for a successful search: O (___ n ____) Average-case for an unsuccessful search: O (_ 1 _) Average-case for a successful search: O (___ 1 ____)
A hash table that uses chaining with separate lists has 101 buckets and contains 125 data items. What is the load factor of the table? ____ λ = 125/101 ____________ • What are the minimum and maximum values for the load factor of a hash table that uses open probing?Minimum load factor ___ 0 ______Maximum load factor ___ 1 ____
Hash Class rehash() • The method rehash() takes the size ofthe new hash table as an argument performs rehashing. • Create a new table with the specified size and cycle through the nodes in the original table. For each node, use the hashValue field modulo the new table size to hash to the new index. Insert the node at the front of the linked list.
Hash Class rehash()(continued) private void rehash(int newTableSize) { // allocate the new hash table and // record a reference to the current // one in oldTable Entry[] newTable = new Entry[newTableSize], oldTable = table; Entry<T> entry, nextEntry; int index; // cycle through the current hash table for (int i=0; i < table.length; i++) { // record the current entry entry = table[i];
Hash Class rehash() (cont) // see if there is a linked list present if (entry != null) { // have at least one element in a linked list do { // record the next entry in the // original linked list nextEntry = entry.next; // compute the new table index index = entry.hashValue % newTableSize; // insert entry the front of the // new table's linked list at // location index entry.next = newTable[index]; newTable[index] = entry;
Hash Class rehash()(concluded) // assign the next entry in the // original linked list to entry entry = nextEntry; } while (entry != null); } } // the table is now newTable table = newTable; // update the table threshold tableThreshold = (int)(table.length * MAX_LOAD_FACTOR); // let garbage collection get rid of oldTable oldTable = null; }
Hash remove() • Compute the hash table index. Using variables prev and curr that move through the linked list in tandem, search for item. If not present, return false; otherwise, remove item from the list. If prev == null, this involves updating table[index] to reference the successor to the front of the list. Decrement hashTableSize, increment modCount, and return true.
Hash remove() (continued) public boolean remove(Object item) { // compute the hash table index int index = (item.hashCode() & Integer.MAX_VALUE) % table.length; Entry<T> curr, prev; // curr references the front of a // linked list of colliding values; // initialize prev to null curr = table[index]; prev = null; // scan the linked list for item while (curr != null) if (curr.value.equals(item)) { // we have located item and will remove // it; increment modCount modCount++;
Hash remove() (continued) // if prev is not null, curr is not the front // of the list; just skip over curr if (prev != null) prev.next = curr.next; else // curr is front of the list; the // new front of the list is curr.next table[index] = curr.next; // decrement hash table size and return true hashTableSize--; return true; }
Hash remove() (concluded) else { // move prev and curr forward prev = curr; curr = curr.next; } return false; }