mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-12 14:42:03 +08:00
Enhance docs, add tests in LinearProbingHashMap
(#5977)
This commit is contained in:
@ -2,24 +2,51 @@ package com.thealgorithms.datastructures.hashmap.hashing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/***
|
||||
* This class is an implementation of a hash table using linear probing.
|
||||
/**
|
||||
* This class implements a hash table using linear probing to resolve collisions.
|
||||
* Linear probing is a collision resolution method where each slot in the hash table is checked in a sequential manner
|
||||
* until an empty slot is found.
|
||||
*
|
||||
* <p>
|
||||
* The class allows for storing key-value pairs, where both the key and value are generic types.
|
||||
* The key must be of a type that implements the Comparable interface to ensure that the keys can be compared for sorting.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This implementation supports basic operations such as:
|
||||
* <ul>
|
||||
* <li><b>put(Key key, Value value)</b>: Adds a key-value pair to the hash table. If the key already exists, its value is updated.</li>
|
||||
* <li><b>get(Key key)</b>: Retrieves the value associated with the given key.</li>
|
||||
* <li><b>delete(Key key)</b>: Removes the key and its associated value from the hash table.</li>
|
||||
* <li><b>contains(Key key)</b>: Checks if the hash table contains a given key.</li>
|
||||
* <li><b>size()</b>: Returns the number of key-value pairs in the hash table.</li>
|
||||
* <li><b>keys()</b>: Returns an iterable collection of keys stored in the hash table.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The internal size of the hash table is automatically resized when the load factor exceeds 0.5 or falls below 0.125,
|
||||
* ensuring efficient space utilization.
|
||||
* </p>
|
||||
*
|
||||
* @see <a href="https://en.wikipedia.org/wiki/Linear_probing">Linear Probing Hash Table</a>
|
||||
*
|
||||
* @param <Key> keys type.
|
||||
* @param <Value> values type.
|
||||
* @param <Key> the type of keys maintained by this map
|
||||
* @param <Value> the type of mapped values
|
||||
*/
|
||||
public class LinearProbingHashMap<Key extends Comparable<Key>, Value> extends Map<Key, Value> {
|
||||
private int hsize; // size of the hash table
|
||||
private Key[] keys;
|
||||
private Value[] values;
|
||||
private int size; // amount of elements in the hash table
|
||||
private Key[] keys; // array to store keys
|
||||
private Value[] values; // array to store values
|
||||
private int size; // number of elements in the hash table
|
||||
|
||||
// Default constructor initializes the table with a default size of 16
|
||||
public LinearProbingHashMap() {
|
||||
this(16);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
// Constructor to initialize the hash table with a specified size
|
||||
public LinearProbingHashMap(int size) {
|
||||
this.hsize = size;
|
||||
keys = (Key[]) new Comparable[size];
|
||||
@ -81,7 +108,7 @@ public class LinearProbingHashMap<Key extends Comparable<Key>, Value> extends Ma
|
||||
|
||||
i = increment(i);
|
||||
while (keys[i] != null) {
|
||||
// delete keys[i] an vals[i] and reinsert
|
||||
// Save the key and value for rehashing
|
||||
Key keyToRehash = keys[i];
|
||||
Value valToRehash = values[i];
|
||||
keys[i] = null;
|
||||
|
@ -1,8 +1,91 @@
|
||||
package com.thealgorithms.datastructures.hashmap.hashing;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class LinearProbingHashMapTest extends MapTest {
|
||||
|
||||
@Override
|
||||
<Key extends Comparable<Key>, Value> Map<Key, Value> getMap() {
|
||||
return new LinearProbingHashMap<>();
|
||||
}
|
||||
|
||||
@Test
|
||||
void putNullKey() {
|
||||
Map<Integer, String> map = getMap();
|
||||
assertFalse(map.put(null, "value"), "Putting a null key should return false");
|
||||
}
|
||||
|
||||
@Test
|
||||
void putDuplicateKeys() {
|
||||
Map<Integer, String> map = getMap();
|
||||
map.put(1, "one");
|
||||
map.put(1, "uno");
|
||||
assertEquals("uno", map.get(1), "Value should be updated to 'uno'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void putResizeTest() {
|
||||
Map<Integer, String> map = getMap();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
map.put(i, String.valueOf(i));
|
||||
}
|
||||
assertEquals(20, map.size(), "Map size should be 20 after inserting 20 elements");
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteNonExistentKey() {
|
||||
Map<Integer, String> map = getMap();
|
||||
assertFalse(map.delete(999), "Deleting a non-existent key should return false");
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteAndReinsert() {
|
||||
Map<Integer, String> map = getMap();
|
||||
map.put(1, "one");
|
||||
map.delete(1);
|
||||
assertFalse(map.contains(1), "Map should not contain the deleted key");
|
||||
map.put(1, "one again");
|
||||
assertTrue(map.contains(1), "Map should contain the key after reinsertion");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resizeDown() {
|
||||
Map<Integer, String> map = getMap();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
map.put(i, String.valueOf(i));
|
||||
}
|
||||
for (int i = 0; i < 12; i++) {
|
||||
map.delete(i);
|
||||
}
|
||||
assertEquals(4, map.size(), "Map size should be 4 after deleting 12 elements");
|
||||
}
|
||||
|
||||
@Test
|
||||
void keysOrderTest() {
|
||||
Map<Integer, String> map = getMap();
|
||||
for (int i = 10; i > 0; i--) {
|
||||
map.put(i, String.valueOf(i));
|
||||
}
|
||||
int expectedKey = 1;
|
||||
for (Integer key : map.keys()) {
|
||||
assertEquals(expectedKey++, key, "Keys should be in sorted order");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void stressTest() {
|
||||
Map<Integer, String> map = getMap();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
map.put(i, String.valueOf(i));
|
||||
assertEquals(i + 1, map.size(), "Size should match number of inserted elements");
|
||||
}
|
||||
for (int i = 0; i < 500; i++) {
|
||||
map.delete(i);
|
||||
assertEquals(1000 - (i + 1), map.size(), "Size should decrease correctly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user