HashTable.java 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /**
  2. * Hashtable implementation
  3. * Contains Iterator
  4. *
  5. * Project 2
  6. *
  7. * @author Thomas Flucke tflucke
  8. * @author Lara Luu ljluu
  9. *
  10. * @since 2015/11/11
  11. *
  12. * @see Comparable
  13. */
  14. import java.util.Iterator;
  15. import java.util.NoSuchElementException;
  16. public class HashTable
  17. {
  18. /**
  19. * A private class used by Hashtable
  20. * Creates HashEntries to be used in the hashtable consisting of an element (type Object) and a boolean active
  21. *
  22. * Project 4
  23. *
  24. * @author Thomas Flucke tflucke
  25. * @author Lara Luu ljluu
  26. *
  27. * @since 2015/10/21
  28. */
  29. private class HashEntry
  30. {
  31. public Object elm; // element stored in the hashEntry
  32. public boolean active; // boolean stating whether or not the entry can be used (used for "deleting" an entry)
  33. /**
  34. * Constructor creating a new hash entry of Object type
  35. */
  36. public HashEntry(Object elm)
  37. {
  38. this.elm = elm;
  39. active = true;
  40. }
  41. }
  42. private HashEntry[] table; // Creates the table array in which the hash entries will be held
  43. private int size; // parameter for the number of elements inside the hashtable
  44. /**
  45. * Constructor creating a new hash table
  46. * Length of the array: next prime number after doubling the capacity
  47. */
  48. public HashTable(int tableCapacity)
  49. {
  50. table = new HashEntry[nextPrime(2*tableCapacity)];
  51. size = 0;
  52. }
  53. /**
  54. * Method returning whether or not the parameter (num) is prime
  55. * @param num
  56. * @return true if the input is prime, false otherwise
  57. */
  58. private static boolean isPrime(int num)
  59. {
  60. if (num % 2 == 0)
  61. {
  62. return false;
  63. }
  64. for (int i = 3; i*i <= num; i += 2)
  65. {
  66. if (num % i == 0)
  67. {
  68. return false;
  69. }
  70. }
  71. return true;
  72. }
  73. /**
  74. * Method for finding the next prime number specified in the parameter (num)
  75. * @param num
  76. * @return the next prime integer
  77. */
  78. private static int nextPrime(int num)
  79. {
  80. if (num % 2 == 0)
  81. {
  82. num++;
  83. }
  84. while (!isPrime(num))
  85. {
  86. num += 2;
  87. }
  88. return num;
  89. }
  90. /**
  91. * Method returning whether or not a hashEntry is active
  92. * @param entry
  93. * @return true if the hashEntry is active, false if it is not
  94. */
  95. private static boolean isActive(HashEntry entry)
  96. {
  97. return entry != null && entry.active;
  98. }
  99. /**
  100. * A private class used by Hashtable
  101. * Visits each number in the order of its hash
  102. *
  103. * Project 4
  104. *
  105. * @author Thomas Flucke tflucke
  106. * @author Lara Luu ljluu
  107. *
  108. * @since 2015/10/21
  109. */
  110. private class Iter implements Iterator<Object>
  111. {
  112. private int cursor; // cursor: points to current location on the hashTable
  113. /**
  114. * Constructor creating an iterator
  115. * cursor starts at -1
  116. */
  117. public Iter()
  118. {
  119. cursor = -1;
  120. findNextElm();
  121. }
  122. /**
  123. * function moving the cursor onto the next element
  124. */
  125. private void findNextElm()
  126. {
  127. cursor++;
  128. while (cursor < table.length && !isActive(table[cursor]))
  129. {
  130. cursor++;
  131. }
  132. }
  133. /**
  134. * Returning a boolean stating whether or not there is a next node
  135. */
  136. @Override
  137. public boolean hasNext() {
  138. return cursor < table.length;
  139. }
  140. /**
  141. * Returns the next element in the in-level traversal
  142. */
  143. @Override
  144. public Object next() {
  145. if (!hasNext())
  146. {
  147. throw new NoSuchElementException();
  148. }
  149. Object tmp = table[cursor].elm; //temp variable holding the value of the cursor
  150. findNextElm();
  151. return tmp;
  152. }
  153. /**
  154. * throws an UnsupportedOperationException; is not meant to be used in the class
  155. */
  156. @Override
  157. public void remove() {
  158. throw new UnsupportedOperationException();
  159. }
  160. }
  161. /**
  162. * Method inserting an element of type Object in the hashTable
  163. * resizes the hashtable if it the size of the hashTable is greater than half of the hashTable
  164. * @param item
  165. */
  166. public void insert(Object item)
  167. {
  168. int index = findNextIndex(item);
  169. if (table[index] == null)
  170. {
  171. table[index] = new HashEntry(item);
  172. size++;
  173. }
  174. else
  175. {
  176. table[index].active = true;
  177. }
  178. if (size >= table.length / 2)
  179. {
  180. rehash();
  181. }
  182. }
  183. /**
  184. * Returns the unique identifier for the object
  185. * @param obj
  186. * @return the index of the array where the element will be stored (hash)
  187. */
  188. private int hash(Object obj)
  189. {
  190. return Math.abs(obj.hashCode()) % table.length;
  191. }
  192. /**
  193. * finds the next available index for the object to be stored if the first spot is already taken
  194. * @param obj
  195. * @return the next index where the object will be stored
  196. */
  197. private int findNextIndex(Object obj)
  198. {
  199. int hash = hash(obj);
  200. int i = 0;
  201. int index = hash;
  202. while (table[index] != null && !table[index].elm.equals(obj))
  203. {
  204. i++;
  205. index = (hash + i*i) % table.length;
  206. }
  207. return index;
  208. }
  209. /**
  210. * Creates a new hashtable twice the size of the old hashTable
  211. * Moves all the old elements into the new hashTable
  212. */
  213. private void rehash()
  214. {
  215. HashEntry[] tmp = table; //creates temporary table twice the size of the old one
  216. table = new HashEntry[nextPrime(table.length*2)];
  217. for (HashEntry he : tmp)
  218. {
  219. if (isActive(he))
  220. {
  221. insert(he.elm);
  222. }
  223. }
  224. }
  225. /**
  226. * Method "deleting" the specified element in the hashTable
  227. * To "delete": makes the element inactive by changing the active instance variable to "false"
  228. * @param item
  229. */
  230. public void delete(Object item)
  231. {
  232. int index = findNextIndex(item);
  233. if (table[index] != null)
  234. {
  235. table[index].active = false;
  236. }
  237. }
  238. /**
  239. * Method to find the specified item in the hashTable
  240. *
  241. * @param item
  242. * @return the index at which the item is located, returns null if the item is not located in the hashTable
  243. */
  244. public Object find(Object item)
  245. {
  246. int index = findNextIndex(item);
  247. if (isActive(table[index]))
  248. {
  249. return table[index].elm;
  250. }
  251. return null;
  252. }
  253. /**
  254. * Counts the number of entries in the hashtable
  255. * @return an integer for the amount of items in a hashTable
  256. */
  257. public int elementCount()
  258. {
  259. int count = 0; // integer counting the amount of items in an object
  260. for (HashEntry he : table)
  261. {
  262. if (isActive(he))
  263. {
  264. count++;
  265. }
  266. }
  267. return count;
  268. }
  269. /**
  270. * Method seeing whether or not the hashTable is empty
  271. * @return true if the hashTable is empty, false if it is not
  272. */
  273. public boolean isEmpty()
  274. {
  275. for (HashEntry he : table)
  276. {
  277. if (isActive(he))
  278. {
  279. return false;
  280. }
  281. }
  282. return true;
  283. }
  284. /**
  285. * Empties the hashTable of all elements
  286. */
  287. public void makeEmpty()
  288. {
  289. table = new HashEntry[table.length];
  290. }
  291. /**
  292. * Prints out the hashtable in the following format:
  293. * [0]: xxx, active
  294. *[1]: empty
  295. *[2]: yyy, inactive
  296. */
  297. public void printTable()
  298. {
  299. for (int i = 0; i < table.length; i++)
  300. {
  301. System.out.print("["+i+"]: ");
  302. if (table[i] == null)
  303. {
  304. System.out.print("empty");
  305. }
  306. else
  307. {
  308. System.out.print(table[i].elm);
  309. System.out.print(", ");
  310. System.out.print(table[i].active? "active":"inactive");
  311. }
  312. System.out.println();
  313. }
  314. }
  315. /**
  316. * Constructor creating a new iterator
  317. * @return a new Iterator
  318. */
  319. @SuppressWarnings("rawtypes")
  320. public Iterator iterator()
  321. {
  322. return new Iter();
  323. }
  324. }