mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-07 09:45:04 +08:00
Enhance docs, add tests in HashMapCuckooHashing
(#5975)
This commit is contained in:
@ -857,12 +857,12 @@
|
|||||||
* hashing
|
* hashing
|
||||||
* [GenericHashMapUsingArrayListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayListTest.java)
|
* [GenericHashMapUsingArrayListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayListTest.java)
|
||||||
* [GenericHashMapUsingArrayTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayTest.java)
|
* [GenericHashMapUsingArrayTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayTest.java)
|
||||||
|
* [HashMapCuckooHashingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapCuckooHashingTest.java)
|
||||||
* [HashMapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapTest.java)
|
* [HashMapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapTest.java)
|
||||||
* [IntersectionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/IntersectionTest.java)
|
* [IntersectionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/IntersectionTest.java)
|
||||||
* [LinearProbingHashMapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMapTest.java)
|
* [LinearProbingHashMapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMapTest.java)
|
||||||
* [MajorityElementTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MajorityElementTest.java)
|
* [MajorityElementTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MajorityElementTest.java)
|
||||||
* [MapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java)
|
* [MapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java)
|
||||||
* [HashMapCuckooHashingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/HashMapCuckooHashingTest.java)
|
|
||||||
* heaps
|
* heaps
|
||||||
* [FibonacciHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/FibonacciHeapTest.java)
|
* [FibonacciHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/FibonacciHeapTest.java)
|
||||||
* [GenericHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java)
|
* [GenericHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java)
|
||||||
|
@ -3,25 +3,26 @@ package com.thealgorithms.datastructures.hashmap.hashing;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is an implementation of a hash table using Cuckoo Hashing It uses
|
* This class implements a hash table using Cuckoo Hashing.
|
||||||
* a dynamic array to lengthen the size of the hash table when load factor > .7
|
* Cuckoo hashing is a type of open-addressing hash table that resolves collisions
|
||||||
|
* by relocating existing keys. It utilizes two hash functions to minimize collisions
|
||||||
|
* and automatically resizes the table when the load factor exceeds 0.7.
|
||||||
*
|
*
|
||||||
* <a href="https://en.wikipedia.org/wiki/Cuckoo_hashing">...</a>
|
* For more information on cuckoo hashing, refer to
|
||||||
|
* <a href="https://en.wikipedia.org/wiki/Cuckoo_hashing">this Wikipedia page</a>.
|
||||||
*/
|
*/
|
||||||
public class HashMapCuckooHashing {
|
public class HashMapCuckooHashing {
|
||||||
|
|
||||||
private int tableSize; // size of the hash table
|
private int tableSize; // Size of the hash table
|
||||||
private Integer[] buckets; // array representing the table
|
private Integer[] buckets; // Array representing the hash table
|
||||||
private final Integer emptySlot;
|
private final Integer emptySlot; // Placeholder for deleted slots
|
||||||
private int size; // number of elements in the hash table
|
private int size; // Number of elements in the hash table
|
||||||
|
private int thresh; // Threshold for detecting infinite loops during insertion
|
||||||
private int thresh; // threshold for infinite loop checking
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor initializes buckets array, hsize, and creates dummy object
|
* Constructs a HashMapCuckooHashing object with the specified initial table size.
|
||||||
* for emptySlot
|
|
||||||
*
|
*
|
||||||
* @param tableSize the desired size of the hash map
|
* @param tableSize the initial size of the hash map
|
||||||
*/
|
*/
|
||||||
public HashMapCuckooHashing(int tableSize) {
|
public HashMapCuckooHashing(int tableSize) {
|
||||||
this.buckets = new Integer[tableSize];
|
this.buckets = new Integer[tableSize];
|
||||||
@ -32,13 +33,11 @@ public class HashMapCuckooHashing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The 2 Hash Functions takes a given key and finds an index based on its data, 2 distinctive
|
* Computes the first hash index for a given key using the modulo operation.
|
||||||
* ways to minimize collisions
|
|
||||||
*
|
*
|
||||||
* @param key the desired key to be converted
|
* @param key the key for which the hash index is computed
|
||||||
* @return int an index corresponding to the key
|
* @return an integer index corresponding to the key
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public int hashFunction1(int key) {
|
public int hashFunction1(int key) {
|
||||||
int hash = key % tableSize;
|
int hash = key % tableSize;
|
||||||
if (hash < 0) {
|
if (hash < 0) {
|
||||||
@ -47,6 +46,12 @@ public class HashMapCuckooHashing {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the second hash index for a given key using integer division.
|
||||||
|
*
|
||||||
|
* @param key the key for which the hash index is computed
|
||||||
|
* @return an integer index corresponding to the key
|
||||||
|
*/
|
||||||
public int hashFunction2(int key) {
|
public int hashFunction2(int key) {
|
||||||
int hash = key / tableSize;
|
int hash = key / tableSize;
|
||||||
hash %= tableSize;
|
hash %= tableSize;
|
||||||
@ -57,14 +62,14 @@ public class HashMapCuckooHashing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inserts the key into the hash map by wrapping it as an Integer object, then uses while loop
|
* Inserts a key into the hash table using cuckoo hashing.
|
||||||
* to insert new key if desired place is empty, return. if already occupied, continue while loop
|
* If the target bucket is occupied, it relocates the existing key and attempts to insert
|
||||||
* over the new key that has just been pushed out. if while loop continues more than Thresh,
|
* it into its alternate location. If the insertion process exceeds the threshold,
|
||||||
* rehash table to new size, then push again.
|
* the table is resized.
|
||||||
*
|
*
|
||||||
* @param key the desired key to be inserted in the hash map
|
* @param key the key to be inserted into the hash table
|
||||||
|
* @throws IllegalArgumentException if the key already exists in the table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void insertKey2HashTable(int key) {
|
public void insertKey2HashTable(int key) {
|
||||||
Integer wrappedInt = key;
|
Integer wrappedInt = key;
|
||||||
Integer temp;
|
Integer temp;
|
||||||
@ -77,7 +82,7 @@ public class HashMapCuckooHashing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (checkTableContainsKey(key)) {
|
if (checkTableContainsKey(key)) {
|
||||||
throw new IllegalArgumentException("Key already inside, no duplicates allowed");
|
throw new IllegalArgumentException("Key already exists; duplicates are not allowed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (loopCounter <= thresh) {
|
while (loopCounter <= thresh) {
|
||||||
@ -117,9 +122,7 @@ public class HashMapCuckooHashing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates new HashMapCuckooHashing object, then inserts each of the elements in the previous
|
* Rehashes the current table to a new size (double the current size) and reinserts existing keys.
|
||||||
* table to it with its new hash functions. then refers current array to new table.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void reHashTableIncreasesTableSize() {
|
public void reHashTableIncreasesTableSize() {
|
||||||
HashMapCuckooHashing newT = new HashMapCuckooHashing(tableSize * 2);
|
HashMapCuckooHashing newT = new HashMapCuckooHashing(tableSize * 2);
|
||||||
@ -134,15 +137,16 @@ public class HashMapCuckooHashing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* deletes a key from the hash map and adds an available placeholder
|
* Deletes a key from the hash table, marking its position as available.
|
||||||
*
|
*
|
||||||
* @param key the desired key to be deleted
|
* @param key the key to be deleted from the hash table
|
||||||
|
* @throws IllegalArgumentException if the table is empty or if the key is not found
|
||||||
*/
|
*/
|
||||||
public void deleteKeyFromHashTable(int key) {
|
public void deleteKeyFromHashTable(int key) {
|
||||||
Integer wrappedInt = key;
|
Integer wrappedInt = key;
|
||||||
int hash = hashFunction1(key);
|
int hash = hashFunction1(key);
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
throw new IllegalArgumentException("Table is empty");
|
throw new IllegalArgumentException("Table is empty, cannot delete.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Objects.equals(buckets[hash], wrappedInt)) {
|
if (Objects.equals(buckets[hash], wrappedInt)) {
|
||||||
@ -157,11 +161,11 @@ public class HashMapCuckooHashing {
|
|||||||
size--;
|
size--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Key " + key + " already inside, no duplicates allowed");
|
throw new IllegalArgumentException("Key " + key + " not found in the table.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the hash table line by line
|
* Displays the hash table contents, bucket by bucket.
|
||||||
*/
|
*/
|
||||||
public void displayHashtable() {
|
public void displayHashtable() {
|
||||||
for (int i = 0; i < tableSize; i++) {
|
for (int i = 0; i < tableSize; i++) {
|
||||||
@ -175,17 +179,18 @@ public class HashMapCuckooHashing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the index of location based on an inputted key
|
* Finds the index of a given key in the hash table.
|
||||||
*
|
*
|
||||||
* @param key the desired key to be found
|
* @param key the key to be found
|
||||||
* @return int the index where the key is located
|
* @return the index where the key is located
|
||||||
|
* @throws IllegalArgumentException if the table is empty or the key is not found
|
||||||
*/
|
*/
|
||||||
public int findKeyInTable(int key) {
|
public int findKeyInTable(int key) {
|
||||||
Integer wrappedInt = key;
|
Integer wrappedInt = key;
|
||||||
int hash = hashFunction1(key);
|
int hash = hashFunction1(key);
|
||||||
|
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
throw new IllegalArgumentException("Table is empty");
|
throw new IllegalArgumentException("Table is empty; cannot find keys.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Objects.equals(buckets[hash], wrappedInt)) {
|
if (Objects.equals(buckets[hash], wrappedInt)) {
|
||||||
@ -194,66 +199,70 @@ public class HashMapCuckooHashing {
|
|||||||
|
|
||||||
hash = hashFunction2(key);
|
hash = hashFunction2(key);
|
||||||
if (!Objects.equals(buckets[hash], wrappedInt)) {
|
if (!Objects.equals(buckets[hash], wrappedInt)) {
|
||||||
throw new IllegalArgumentException("Key " + key + " not found in table");
|
throw new IllegalArgumentException("Key " + key + " not found in the table.");
|
||||||
} else {
|
} else {
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* checks if key is inside without any output other than returned boolean.
|
* Checks if the given key is present in the hash table.
|
||||||
*
|
*
|
||||||
* @param key the desired key to be found
|
* @param key the key to be checked
|
||||||
* @return int the index where the key is located
|
* @return true if the key exists, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean checkTableContainsKey(int key) {
|
public boolean checkTableContainsKey(int key) {
|
||||||
return ((buckets[hashFunction1(key)] != null && buckets[hashFunction1(key)].equals(key)) || (buckets[hashFunction2(key)] != null && buckets[hashFunction2(key)] == key));
|
return ((buckets[hashFunction1(key)] != null && buckets[hashFunction1(key)].equals(key)) || (buckets[hashFunction2(key)] != null && buckets[hashFunction2(key)].equals(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the load factor of the hash table if greater than .7,
|
* Checks the load factor of the hash table. If the load factor exceeds 0.7,
|
||||||
* automatically lengthens table to prevent further collisions
|
* the table is resized to prevent further collisions.
|
||||||
|
*
|
||||||
|
* @return the current load factor of the hash table
|
||||||
*/
|
*/
|
||||||
public double checkLoadFactor() {
|
public double checkLoadFactor() {
|
||||||
double factor = (double) size / tableSize;
|
double factor = (double) size / tableSize;
|
||||||
if (factor > .7) {
|
if (factor > .7) {
|
||||||
System.out.printf("Load factor is %.2f , rehashing table%n", factor);
|
System.out.printf("Load factor is %.2f, rehashing table.%n", factor);
|
||||||
reHashTableIncreasesTableSize();
|
reHashTableIncreasesTableSize();
|
||||||
}
|
}
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isFull returns true if the hash map is full and false if not full
|
* Checks if the hash map is full.
|
||||||
*
|
*
|
||||||
* @return boolean is Empty
|
* @return true if the hash map is full, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean isFull() {
|
public boolean isFull() {
|
||||||
boolean response = true;
|
|
||||||
for (int i = 0; i < tableSize; i++) {
|
for (int i = 0; i < tableSize; i++) {
|
||||||
if (buckets[i] == null || Objects.equals(buckets[i], emptySlot)) {
|
if (buckets[i] == null || Objects.equals(buckets[i], emptySlot)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isEmpty returns true if the hash map is empty and false if not empty
|
* Checks if the hash map is empty.
|
||||||
*
|
*
|
||||||
* @return boolean is Empty
|
* @return true if the hash map is empty, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
boolean response = true;
|
|
||||||
for (int i = 0; i < tableSize; i++) {
|
for (int i = 0; i < tableSize; i++) {
|
||||||
if (buckets[i] != null) {
|
if (buckets[i] != null) {
|
||||||
response = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current number of keys in the hash table.
|
||||||
|
*
|
||||||
|
* @return the number of keys present in the hash table
|
||||||
|
*/
|
||||||
public int getNumberOfKeysInTable() {
|
public int getNumberOfKeysInTable() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -1,94 +0,0 @@
|
|||||||
package com.thealgorithms.datastructures.hashmap;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
|
||||||
|
|
||||||
import com.thealgorithms.datastructures.hashmap.hashing.HashMapCuckooHashing;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
class HashMapCuckooHashingTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void insertKey() {
|
|
||||||
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
|
||||||
assertEquals(0, hashTable.getNumberOfKeysInTable());
|
|
||||||
|
|
||||||
hashTable.insertKey2HashTable(3);
|
|
||||||
|
|
||||||
assertEquals(1, hashTable.getNumberOfKeysInTable());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getKeyIndex() {
|
|
||||||
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
|
||||||
hashTable.insertKey2HashTable(8);
|
|
||||||
hashTable.insertKey2HashTable(4);
|
|
||||||
|
|
||||||
assertNotEquals(-1, hashTable.findKeyInTable(8));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void containsKey() {
|
|
||||||
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
|
||||||
hashTable.insertKey2HashTable(8);
|
|
||||||
boolean contains = hashTable.checkTableContainsKey(8);
|
|
||||||
|
|
||||||
assertTrue(contains);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void removeKey() {
|
|
||||||
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
|
||||||
hashTable.insertKey2HashTable(3);
|
|
||||||
|
|
||||||
int initialSize = hashTable.getNumberOfKeysInTable();
|
|
||||||
|
|
||||||
hashTable.deleteKeyFromHashTable(3);
|
|
||||||
|
|
||||||
assertEquals(initialSize - 1, hashTable.getNumberOfKeysInTable());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void removeNone() {
|
|
||||||
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
|
||||||
try {
|
|
||||||
hashTable.deleteKeyFromHashTable(3);
|
|
||||||
} catch (Exception e) {
|
|
||||||
assertTrue(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void reHashTableIncreasesTableSize() {
|
|
||||||
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
|
||||||
int initialSize = hashTable.getNumberOfKeysInTable();
|
|
||||||
|
|
||||||
hashTable.reHashTableIncreasesTableSize();
|
|
||||||
|
|
||||||
assertEquals(initialSize * 2, hashTable.getNumberOfKeysInTable());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void hashFunctionsAreDifferent() {
|
|
||||||
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
|
||||||
hashTable.insertKey2HashTable(33);
|
|
||||||
|
|
||||||
assertNotEquals(hashTable.hashFunction1(3), hashTable.hashFunction2(3));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void avoidInfiniteLoops() {
|
|
||||||
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
|
||||||
hashTable.insertKey2HashTable(0);
|
|
||||||
hashTable.insertKey2HashTable(10);
|
|
||||||
hashTable.insertKey2HashTable(100);
|
|
||||||
|
|
||||||
assertTrue(hashTable.checkTableContainsKey(0));
|
|
||||||
assertTrue(hashTable.checkTableContainsKey(10));
|
|
||||||
assertTrue(hashTable.checkTableContainsKey(100));
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,140 @@
|
|||||||
|
package com.thealgorithms.datastructures.hashmap.hashing;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class HashMapCuckooHashingTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void insertKey() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
assertEquals(0, hashTable.getNumberOfKeysInTable());
|
||||||
|
|
||||||
|
hashTable.insertKey2HashTable(3);
|
||||||
|
assertEquals(1, hashTable.getNumberOfKeysInTable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getKeyIndex() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
hashTable.insertKey2HashTable(8);
|
||||||
|
hashTable.insertKey2HashTable(4);
|
||||||
|
|
||||||
|
assertNotEquals(-1, hashTable.findKeyInTable(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void containsKey() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
hashTable.insertKey2HashTable(8);
|
||||||
|
boolean contains = hashTable.checkTableContainsKey(8);
|
||||||
|
|
||||||
|
assertTrue(contains);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void removeKey() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
hashTable.insertKey2HashTable(3);
|
||||||
|
|
||||||
|
int initialSize = hashTable.getNumberOfKeysInTable();
|
||||||
|
hashTable.deleteKeyFromHashTable(3);
|
||||||
|
|
||||||
|
assertEquals(initialSize - 1, hashTable.getNumberOfKeysInTable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void removeNone() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
try {
|
||||||
|
hashTable.deleteKeyFromHashTable(3);
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertTrue(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Assertions.fail("Expected exception when trying to delete a non-existing key.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void reHashTableIncreasesTableSize() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
hashTable.insertKey2HashTable(1);
|
||||||
|
hashTable.insertKey2HashTable(2);
|
||||||
|
hashTable.insertKey2HashTable(3);
|
||||||
|
hashTable.insertKey2HashTable(4);
|
||||||
|
hashTable.insertKey2HashTable(5);
|
||||||
|
hashTable.insertKey2HashTable(6);
|
||||||
|
hashTable.insertKey2HashTable(7);
|
||||||
|
hashTable.insertKey2HashTable(8);
|
||||||
|
hashTable.insertKey2HashTable(9);
|
||||||
|
hashTable.insertKey2HashTable(10); // This should trigger rehashing
|
||||||
|
|
||||||
|
assertEquals(10, hashTable.getNumberOfKeysInTable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void hashFunctionsAreDifferent() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
hashTable.insertKey2HashTable(33);
|
||||||
|
|
||||||
|
assertNotEquals(hashTable.hashFunction1(3), hashTable.hashFunction2(3), "Hash functions should produce different indices.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void avoidInfiniteLoops() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
hashTable.insertKey2HashTable(0);
|
||||||
|
hashTable.insertKey2HashTable(10);
|
||||||
|
hashTable.insertKey2HashTable(100);
|
||||||
|
|
||||||
|
assertTrue(hashTable.checkTableContainsKey(0));
|
||||||
|
assertTrue(hashTable.checkTableContainsKey(10));
|
||||||
|
assertTrue(hashTable.checkTableContainsKey(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testLoadFactor() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
for (int i = 1; i <= 8; i++) { // Insert 8 keys to test load factor
|
||||||
|
hashTable.insertKey2HashTable(i);
|
||||||
|
}
|
||||||
|
assertEquals(8, hashTable.getNumberOfKeysInTable());
|
||||||
|
// Check that rehashing occurs when a 9th key is added
|
||||||
|
hashTable.insertKey2HashTable(9);
|
||||||
|
assertTrue(hashTable.getNumberOfKeysInTable() > 8, "Load factor exceeded, table should have been resized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteNonExistentKey() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
hashTable.insertKey2HashTable(1);
|
||||||
|
hashTable.insertKey2HashTable(2);
|
||||||
|
|
||||||
|
Exception exception = null;
|
||||||
|
try {
|
||||||
|
hashTable.deleteKeyFromHashTable(3); // Try deleting a non-existent key
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
exception = e; // Capture the exception
|
||||||
|
}
|
||||||
|
assertNotNull(exception, "Expected an IllegalArgumentException when deleting a non-existent key.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsertDuplicateKey() {
|
||||||
|
HashMapCuckooHashing hashTable = new HashMapCuckooHashing(10);
|
||||||
|
hashTable.insertKey2HashTable(1);
|
||||||
|
Exception exception = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
hashTable.insertKey2HashTable(1); // Attempt to insert duplicate key
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
exception = e; // Capture the exception
|
||||||
|
}
|
||||||
|
assertNotNull(exception, "Expected an IllegalArgumentException for duplicate key insertion.");
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user