// Helene Martin, CSE 143 // Hash table implementation of a set, an unordered collection without duplicates. // The hash table stores values at indexes determined by a hashing function. // O(1) average time to add, remove, search. (YAY!!) // This complete version uses chaining for collision resolution. This is implemented // with linked nodes. The node class is a private inner class (you don't need to know about // this yet). public class HashSet implements Set { private int size; private HashNode[] elementData; // Builds a new HashSet of the specified capacity public HashSet(int capacity) { elementData = new HashNode[capacity]; } // Adds the given value to the set // Pre: There is nothing at indexOf(value) @Override public void add(E value) { if (!contains(value)) { int i = indexOf(value); elementData[i] = new HashNode(value, elementData[i]); size++; } } // Remove the given value from the set @Override public void remove(E value) { if (contains(value)) { int i = indexOf(value); if (elementData[i].data.equals(value)) { elementData[i] = elementData[i].next; } else { HashNode current = elementData[i]; while (!current.next.data.equals(value)) { current = current.next; } current.next = current.next.next; } size--; } } // Checks whether the given value is in the set @Override public boolean contains(E value) { int i = indexOf(value); HashNode current = elementData[i]; while (current != null) { if (current.data.equals(value)) { return true; } current = current.next; } return false; } // Returns the size of the set @Override public int size() { return size; } // Uses the hashing function to find the index of a value. private int indexOf(E value) { return Math.abs(value.hashCode() % elementData.length); } // Private inner class to represent a single hash table // value. Note: we use a linked list for chaining because it has // very fast add at the front and doesn't take much memory. private static class HashNode { public Object data; public HashNode next; // Build a new node with the given data and next reference. public HashNode(Object data, HashNode next) { this.data = data; this.next = next; } } }