From c86f29ccc1060bbb4cb54095be61bb249f8ba23a Mon Sep 17 00:00:00 2001 From: Wouter Groeneveld Date: Tue, 27 Mar 2018 13:03:12 +0200 Subject: [PATCH] update impl --- .../hashtable/DeletedBucket.java | 11 ++++ .../datastructures/hashtable/HashBucket.java | 23 ++++++-- .../datastructures/hashtable/HashTable.java | 54 +++++++++++++------ .../hashtable/IAmBucketable.java | 5 ++ .../hashing/LinearProbeHashTest.java | 25 +++++++++ .../hashtable/HashTableTest.java | 8 ++- 6 files changed, 107 insertions(+), 19 deletions(-) create mode 100644 datastructures/java/src/be/brainbaking/datastructures/hashtable/DeletedBucket.java create mode 100644 datastructures/java/src/be/brainbaking/datastructures/hashtable/IAmBucketable.java create mode 100644 datastructures/java/test/be/brainbaking/datastructures/hashing/LinearProbeHashTest.java diff --git a/datastructures/java/src/be/brainbaking/datastructures/hashtable/DeletedBucket.java b/datastructures/java/src/be/brainbaking/datastructures/hashtable/DeletedBucket.java new file mode 100644 index 0000000..85e09a9 --- /dev/null +++ b/datastructures/java/src/be/brainbaking/datastructures/hashtable/DeletedBucket.java @@ -0,0 +1,11 @@ +package be.brainbaking.datastructures.hashtable; + +public class DeletedBucket implements IAmBucketable { + + private static DeletedBucket bucket = new DeletedBucket(); + + public static DeletedBucket singleton() { + return bucket; + } + +} diff --git a/datastructures/java/src/be/brainbaking/datastructures/hashtable/HashBucket.java b/datastructures/java/src/be/brainbaking/datastructures/hashtable/HashBucket.java index b959229..c4bf96d 100644 --- a/datastructures/java/src/be/brainbaking/datastructures/hashtable/HashBucket.java +++ b/datastructures/java/src/be/brainbaking/datastructures/hashtable/HashBucket.java @@ -1,10 +1,27 @@ package be.brainbaking.datastructures.hashtable; -public class HashBucket { +public class HashBucket implements IAmBucketable { - private final T key; + /** + * the key of the bucket to store the value in + */ + private final Key key; - public HashBucket(T key) { + /** + * "sattelite" data + */ + private final Value value; + + public Value getValue() { + return value; + } + + public Key getKey() { + return key; + } + + public HashBucket(Key key, Value value) { this.key = key; + this.value = value; } } diff --git a/datastructures/java/src/be/brainbaking/datastructures/hashtable/HashTable.java b/datastructures/java/src/be/brainbaking/datastructures/hashtable/HashTable.java index 44f5c0a..51533dc 100644 --- a/datastructures/java/src/be/brainbaking/datastructures/hashtable/HashTable.java +++ b/datastructures/java/src/be/brainbaking/datastructures/hashtable/HashTable.java @@ -3,9 +3,11 @@ package be.brainbaking.datastructures.hashtable; import be.brainbaking.datastructures.hashing.Hashable; import be.brainbaking.datastructures.hashing.LinearProbeHash; -public class HashTable { +import java.util.Arrays; - private final HashBucket[] table; +public class HashTable { + + private final HashBucket[] table; private final Hashable hasher; public HashTable() { @@ -17,32 +19,54 @@ public class HashTable { hasher = new LinearProbeHash(10); } - public void add(T key) { - add(key, 0); + public void put(Key key, Value value) { + put(key, value, 0); } - public void remove(T key) { + public Value remove(Key key) { throw new UnsupportedOperationException(); - // TODO "deleted" stuff + // TODO "deleted" stuff (bestaande calls wijzigen) } - public int search(T key) { - throw new UnsupportedOperationException(); - // TODO return key if exists + public Value get(Key key) { + return get(key, 0); } - private void add(T key, int probeStep) { - if(probeStep > table.length) { + /** + * Géén O(1), maar "gemiddeld" gezien wel, gegeven dat de hash goed gekozen is en we weinig moeten proben. + * @param key key van bucket + * @param probeStep probe start positie + * @return indien niet gevonden, null, anders de bewaarde value + */ + private Value get(Key key, int probeStep) { + int hash = hasher.hash(key, probeStep); + if(hash >= table.length) return null; + + + if(table[hash].getKey() == key) return table[hash].getValue(); + return get(key, probeStep + 1); + } + + /** + * table.length is niet de "size". O(n) nodig, alles overlopen om te kijken wat ingevuld is... Kostelijk! + * @return the size + */ + public int size() { + return (int) Arrays.stream(table).filter(entry -> entry != null).count(); + } + + private void put(Key key, Value value, int probeStep) { + // TODO resizing van tabel indien te groot geworden + int hash = hasher.hash(key, probeStep); + if(hash >= table.length) { throw new UnsupportedOperationException("unable to add key to table, everything occupied?"); } - int hash = hasher.hash(key, probeStep); if(table[hash] != null) { - add(key, probeStep + 1); + put(key, value, probeStep + 1); } else { - table[hash] = new HashBucket<>(key); + table[hash] = new HashBucket<>(key, value); } - } } diff --git a/datastructures/java/src/be/brainbaking/datastructures/hashtable/IAmBucketable.java b/datastructures/java/src/be/brainbaking/datastructures/hashtable/IAmBucketable.java new file mode 100644 index 0000000..8d7d0f7 --- /dev/null +++ b/datastructures/java/src/be/brainbaking/datastructures/hashtable/IAmBucketable.java @@ -0,0 +1,5 @@ +package be.brainbaking.datastructures.hashtable; + +public interface IAmBucketable { + +} diff --git a/datastructures/java/test/be/brainbaking/datastructures/hashing/LinearProbeHashTest.java b/datastructures/java/test/be/brainbaking/datastructures/hashing/LinearProbeHashTest.java new file mode 100644 index 0000000..a3680b1 --- /dev/null +++ b/datastructures/java/test/be/brainbaking/datastructures/hashing/LinearProbeHashTest.java @@ -0,0 +1,25 @@ +package be.brainbaking.datastructures.hashing; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class LinearProbeHashTest { + + @Test + public void shouldHashingBeRecalculated_ifMaximumChanges() { + LinearProbeHash hash10 = new LinearProbeHash(10); + LinearProbeHash hash15 = new LinearProbeHash(15); + + int hashed10 = hash10.hash((Integer) 123, 0); + int hashed15 = hash15.hash((Integer) 123, 0); + + assertEquals(hashed15, hashed10); + + int hashed10Bigger = hash10.hash((Integer) 123456789, 0); + int hashed15Bigger = hash15.hash((Integer) 123456789, 0); + + assertEquals(hashed15Bigger, hashed10Bigger); + } + +} diff --git a/datastructures/java/test/be/brainbaking/datastructures/hashtable/HashTableTest.java b/datastructures/java/test/be/brainbaking/datastructures/hashtable/HashTableTest.java index fd72cbd..324880e 100644 --- a/datastructures/java/test/be/brainbaking/datastructures/hashtable/HashTableTest.java +++ b/datastructures/java/test/be/brainbaking/datastructures/hashtable/HashTableTest.java @@ -2,11 +2,17 @@ package be.brainbaking.datastructures.hashtable; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class HashTableTest { @Test - public void add() { + public void add_increasesSize_andAbleToGetValue() { + HashTable table = new HashTable<>(); + table.put(123, 445); + assertEquals(1, table.size()); + assertEquals(445, (int) table.get(123)); } }