Guest User

Untitled

a guest
Nov 11th, 2016
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.68 KB | None | 0 0
  1. import java.util.LinkedHashSet;
  2. import java.util.function.BiFunction;
  3. import java.util.Set;
  4. import java.util.LinkedList;
  5. import java.util.Random;
  6.  
  7. class Entry<K,V> {
  8.     Entry(K k, V v) { key = k; value = v; }
  9.     final K key;
  10.     V value;
  11.     int hash;
  12.  
  13.     public String toString() {
  14.         return "{" +String.valueOf(key) + "=" + String.valueOf(value) + "}";
  15.     }
  16. }
  17.  
  18.  
  19. @SuppressWarnings("unchecked")
  20. public class HashTableImp<K,V> implements HashTable<K,V>{
  21.     // an array of linked lists to handle chaining
  22.     private LinkedList<Entry<K,V>>[] array;
  23.     private int itemCount;
  24.     private BiFunction<K,Integer,Integer> h;
  25.  
  26.     private int hash(K k){
  27.     return this.h.apply(k,this.itemCount);
  28.     }
  29.  
  30.     public HashTableImp(int initialCapacity, HashMethod hm){
  31.     // This cast violates type safety of the program but we wanted
  32.     // you to implement hash table on top of a data structure that
  33.     // does not do dynamic resizing (arrays instead of ArrayList)
  34.     // so you can do the hash table growing yourself.
  35.     // Do NOT do it in the future.
  36. //  this.array = (LinkedList<Entry<K,V>>[]) new Object[initialCapacity];
  37.     this.array = (LinkedList<Entry<K,V>>[]) new LinkedList<?>[initialCapacity];
  38.  
  39.     this.itemCount = 0;
  40.     switch (hm) {
  41.         case Div:
  42.             // division method
  43.             h = (k,m) -> {return k.hashCode() % m;};
  44.             break;
  45.         case MAD:
  46.             h = (k,m) -> {return mad(k,m);};
  47.             break;
  48.         }
  49.     }
  50.  
  51.     // Implement all the following stubs
  52.  
  53.     /* I found this helper function on stackoverflow.com, at
  54.      * http://stackoverflow.com/questions/23644479/find-next-prime-number written by @Ben_Aaronson */
  55.     public int nextPrime(int number) {
  56.         while(true) {
  57.             boolean isPrime = true;
  58.             //increment the number by 1 each time
  59.             number = number + 1;
  60.  
  61.             int x = (int) Math.sqrt(number);
  62.  
  63.             //start at 2 and increment by 1 until it gets to the squared number
  64.             for (int i = 2; i <= x; i++)  {
  65.                 if (number % i == 0) {
  66.                     isPrime = false;
  67.                     break;
  68.                 }
  69.             }
  70.             if (isPrime) return number;
  71.         }
  72.     }
  73.  
  74.     // Multiply-Add-and-Divide (MAD) hashing method
  75.     private int mad(K k, int m) {
  76.         Random rand = new Random();
  77.         /* Select the next prime number greater than m */
  78.         int p = nextPrime(m);
  79.         /* Choose two numbers between 1 and m - 1 */
  80.         int a = rand.nextInt(m) + 1;
  81.         int b = rand.nextInt(m) + 1;
  82.         int index = ((a * k.hashCode() + b) % p) % m;
  83.         return index;
  84.     }
  85.  
  86.     // this method needs to be called appropriately in the put method
  87.     private void growTable() {
  88.         // Instantiate new array double the size
  89.         LinkedList<Entry<K, V>>[] tmp = (LinkedList<Entry<K, V>>[]) new LinkedList<?>[this.array.length * 2];
  90.         for (int i = 0; i < this.array.length; i++) {
  91.             // Visit every chain of our current array
  92.             if (this.array[i] != null) {
  93.                 // If there's a linked list there, instantiate a new linked list
  94.                 // with all the same key, values into the new, expanded array
  95.                 tmp[i] = new LinkedList<Entry<K, V>>(this.array[i]);
  96.             }
  97.         }
  98.         // Set the current array to be the updated expanded array
  99.         this.array = tmp;
  100.     }
  101.  
  102.     @Override
  103.     public boolean containsKey(K key){
  104. //        int index = h.apply(key, this.array.length);
  105. //        LinkedList<Entry<K,V>> chain =  this.array[index];
  106. //        boolean found = false;
  107. //        for (Entry<K,V> item : chain) {
  108. //            if (item.key == key) {
  109. //                found = true;
  110. //            }
  111. //        }
  112. //        return found;
  113.         for (int i = 0; i < this.array.length; i++) {
  114.             if (this.array[i] != null) {
  115.                 for (Entry<K,V> item : this.array[i]) {
  116.                     if (item.key == key) {
  117.                         return true;
  118.                     }
  119.                 }
  120.             }
  121.         }
  122.         return false;
  123.     }
  124.  
  125.     @Override
  126.     public V get(K key) {
  127. //        THIS ONLY WORKS FOR DIV
  128. //        int index = h.apply(key, this.array.length);
  129. //        System.out.println("Trying to grab entry at index " + index);
  130. //        LinkedList<Entry<K,V>> chain =  this.array[index];
  131. //        for (Entry<K,V> item : chain) {
  132. //            if (item.key == key) {
  133. //                return item.value;
  134. //            }
  135. //        }
  136. //        return null; // Should throw an exception
  137.         for (int i = 0; i < this.array.length; i++) {
  138.             if (this.array[i] != null) {
  139.                 for (Entry<K,V> item : this.array[i]) {
  140.                     if (item.key == key) {
  141.                         return item.value;
  142.                     }
  143.                 }
  144.             }
  145.         }
  146.         return null;
  147.     }
  148.  
  149.     @Override
  150.     public V put(K key, V value) {
  151.         int index = h.apply(key, this.array.length);
  152.         if (this.array[index] == null) {
  153.             this.array[index] = new LinkedList<Entry<K,V>>();
  154.         }
  155.         LinkedList<Entry<K,V>> chain =  this.array[index];
  156.         chain.add(new Entry<K,V>(key, value));
  157.         ++itemCount;
  158.  
  159.         // If the array is more than 3/4 full, we need to double the table
  160.         if (itemCount > (this.array.length * 3) / 4) growTable();
  161.         return value;
  162.     }
  163.  
  164.     // not used in this client code so make sure it works correctly by
  165.     // implementing unit tests.
  166.     @Override
  167.     public boolean isEmpty(){
  168.         return itemCount == 0;
  169.     }
  170.  
  171.     @Override
  172.     public Set<K> keySet() {
  173.         LinkedHashSet<K> set = new LinkedHashSet<K>();
  174.         for (int i = 0; i < this.array.length; i++) {
  175.             if (this.array[i] != null) {
  176.                 for (Entry<K,V> item : this.array[i]) {
  177.                     set.add(item.key);
  178.                 }
  179.             }
  180.         }
  181.         return set;
  182.     }
  183.  
  184.     // not used in this client code so make sure it works correctly by
  185.     // implementing unit tests.
  186.     @Override
  187.     public V remove(K key) {
  188. //        int index = h.apply(key, this.array.length);
  189. //        LinkedList<Entry<K,V>> chain =  this.array[index];
  190. //        for (Entry<K,V> item : chain) {
  191. //            if (item.key == key) {
  192. //                chain.remove(item);
  193. //                itemCount--;
  194. //                return item.value;
  195. //            }
  196. //        }
  197. //        return null; // Throw exception
  198.         for (int i = 0; i < this.array.length; i++) {
  199.             if (this.array[i] != null) {
  200.                 for (Entry<K,V> item : this.array[i]) {
  201.                     if (item.key == key) {
  202.                         this.array[i].remove(item);
  203.                         itemCount--;
  204.                         return item.value;
  205.                     }
  206.                 }
  207.             }
  208.         }
  209.         return null;
  210.     }
  211.  
  212.     public String toString() {
  213.         String buf = "";
  214.         for (int i = 0; i < this.array.length; i++) {
  215.             if (this.array[i] != null) {
  216.                 for (Entry<K,V> item : this.array[i]) {
  217.                     buf += item.toString() + " ";
  218.                 }
  219.             }
  220.         }
  221.         return buf;
  222.     }
  223.  
  224.     public void print() {
  225.         for (int i = 0; i < this.array.length; i++) {
  226.             System.out.format("["+i+"] [");
  227.             if (this.array[i] != null) {
  228.                 for (Entry<K,V> item : this.array[i]) {
  229.                     System.out.format("%s ", item.toString());
  230.                 }
  231.             }
  232.             System.out.format("]\n");
  233.         }
  234.     }
  235.  
  236.     public static void main(String[] args) {
  237.         HashTableImp<Character, Integer> HT = new HashTableImp<>(12, HashMethod.MAD);
  238.         Character keys[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',};
  239.         assert HT.isEmpty();
  240.         for (int i = 0; i < keys.length; i++) {
  241.             if (i == (HT.array.length * 3 / 4)) {
  242.                 int tmp = HT.array.length;
  243.                 HT.put(keys[i], i);
  244.                 assert HT.array.length == tmp * 2;
  245. //                System.out.format("Increasing table size from %d to %d\n", tmp, HT.array.length);
  246.             } else {
  247.                 HT.put(keys[i], i);
  248.             }
  249.             assert HT.get(keys[i]) == i;
  250.             assert HT.containsKey(keys[i]);
  251.             assert HT.itemCount == i + 1;
  252.  
  253.         }
  254.         assert ! HT.isEmpty();
  255.         HT.print();
  256.         System.out.println("SET: " + HT.keySet().toString());
  257.         for (int i = 0; i < keys.length; i++) {
  258.             assert HT.get(keys[i]) == HT.remove(keys[i]);
  259.             assert ! HT.containsKey(keys[i]);
  260.         }
  261. //        HT.print();
  262.  
  263.     }
  264. }
Advertisement
Add Comment
Please, Sign In to add comment