The Hashtable class is a C++ template class that provides an implementation of a hash table for storing key-value pairs. It allows you to efficiently store and retrieve data using keys, similar to a dictionary or map in other programming languages.
The Hashtable class is designed to offer a dynamic and scalable hash table with the following features:
- Dynamic Sizing: The hash table dynamically resizes itself when the load factor exceeds a specified threshold, ensuring efficient memory usage.
- Collision Handling: It uses separate chaining to handle collisions, allowing multiple key-value pairs with the same hash value to be stored and retrieved correctly.
- Iterator Support: You can iterate through the keys in the hash table using iterators, making it easy to perform operations on the keys and their associated values.
WARNING: This Library Utilizes POINTERS *. This is due to the Libraries ability to utilize any return type. (Bool, String, int, float, etc)
put(K key, V value): Associates the given key with the specified value in the hash table.get(K key): Retrieves the pointer to the value associated with the given key.getElement(K key): Retrieves the value associated with the given keyremove(K key): Removes the key-value pair associated with the given key.clear(): Clears all key-value pairs from the hash table.size(): Returns the size of the table.elements(): Returns the number of elements in the table.isEmpty(): Checks if the hash table is empty.keys(): Returns an iterator for iterating over the keys in the hash table.merge(const Hashtable<K, V>& other): Merges the contents of another hash table into the current one.containsKey(const K& key): Check if a Table contains a key.containsValue(const V& value): Check if a Table contains a Value.begin(): Begins Iterationend(): ends IterationloadFactor(): Returns calculated load factorcheckLoadFactorAndRehash(): checks the load factor and rehashes the table if neededbucketCount(): returns the number of buckets in the tablebucketSize(): returns the size of a bucket in the tablevalues(): Returns an iterator for iterating over the values in the hash table.exists(): Checks to see if a item exists on the table.
Iterator const Hashtable<K, V, Hash>* ht, int bucket, Entry* entry): hashtable(ht), currentBucket(bucket), currentEntr (entry): Constructorbool operator!=(const Iterator& other): Return currentEntry != other.currentEntry || currentBucket != other.currentBucketIterator& operator++(): Moves iteration to the next element, the returns that elementEntry* operator*(): returns currentEntryfind(): Returns a value associated with the keygetKey()Returns a Vector of KeysgetValues()Returns a Vector of Values
To use the Hashtable class, follow these steps:
- Include the
Hashtable.hheader in your C++ program. - Create an instance of the
Hashtableclass with specific data types for keys and values. - Use the provided methods to add, retrieve, or remove key-value pairs from the hash table.
git clone "https://github.com/braydenanderson2014/C-Arduino-Libraries/tree/main/Hashtable.git"
If you want to Utilize this Library. Please include the
#include <Hashtable.h> - Initial Release. Based off of PlatformIO version v1.1.2
- Added New getKey() Function for Iterator
- Added New getValue() Function for Iterator
- Added New find() Function for Iterator.
- NOTE: All 3 functions are not tested and should be used with Caution.
- RESOLVED ISSUE: Iterator Iterates out of bounds (Issue #85)
- RESOLVED ISSUE: Resizing corrupts data in hashtable (Issue #81)
- RESOLVED ISSUE: get() and getElement() returning incorrectly (Issue #82)
- Added new operator[] function that allows you to access elements by index in the Hashtable
- Added new getBucket() function that returns the bucket at a specific index in the Hashtable
- Added new getBucketSize() function that returns the size of a bucket at a specific index in the Hashtable
- Added new debugIterator() function that iterates the table and prints out the [key, value] pairs.
- Adjusted Iterator operator* function. [FROM THIS]
KeyValuePair operator*() const {
return KeyValuePair{currentEntry->key, currentEntry->value};
}[TO THIS]
KeyValuePair operator*() const {
if (!currentEntry) {
return KeyValuePair{"", ""}; // Return an empty key-value pair if invalid
}
return KeyValuePair{currentEntry->key, currentEntry->value};
}This is to make sure that empty data is printed as empty and not garbage data.
- Adjusted begin() function to return end() instead of
return Iterator(this, TABLE_SIZE, nullptr);which is exactly what end() already has inside. This is just to be neater.
- Removed unnecessary print statements left behind from testing.
- Update is being used to properly progress Arduino Library Manager to next available version due to an error in last update creation.
- No other changes made.
=============================================================================
- Initial Release
- Added Example for how the library works (Example.cpp)
- Added Example for how the library works (Example2.cpp)
- Please Note, This Library Has not been Tested in any Shape or form, USE AT YOUR OWN RISK
- Although this library has not been tested, We do encourage you to use this library so we can find bugs and fix them.
- Added Dynamic Downsize for the Vector to save memory (Useful for Memory Constrained Environments Such As Arduino)
- Added This ChangeLog :)
- Please Note, This Library Has not been Tested in any Shape or form, USE AT YOUR OWN RISK
- Although this library has not been tested, We do encourage you to use this library so we can find bugs and fix them.
- Updated Included Libraries to Latest Version
- Added merge Function that allows you to merge two Hashtables together
- Fixed Issue with get function: Conversion from 'int' to 'const String' is ambiguous. -> Issue appears to happen when you use the get function with a int as the key
- Fixed Hashing Issue: Hashing was not working correctly, causing the get function to not work correctly
- Added containsKey() Function: This function allows you to check if a key exists in the Hashtable
- Added containsValue() Function: This function allows you to check if a value exists in the Hashtable
- Added new Iteration Feature to the library
- Feature is untested
- Repaired Iterator so it now works properly [Tested-Using-Properties-Library]
- Added elements() function to return the number of elements currently on the table.
- Adjusted size() function to return current capacity
- Adjusted clear() function to properly clear the table [Tested-Using-Properties-Library]
- New Overloaded Constructor to allow you to set the initial capacity and load factor
- Added new loadFactor() function to return the current calculated load factor
- Added new checkLoadFactorAndRehash() which checks the load factor and rehashes the table if needed
- Added new bucketCount() function to return the number of buckets in the table
- Added new bucketSize() function to return the size of a bucket
- All new functions are untested, please report any bugs you find!
- These functions are desinged to open up the library to allow you to use it in more ways, such as using it as a hashset
- Added [HASHTABLE]: to the front of each Serial.println() statement to make it easier to debug.
- Modified the Constructor to accept a boolean value to allow you to disable the Serial.print() statements
- Added support for 3 new types: float, double, boolean
- Please note you can add your own specializations for other types if you wish, please see the README.md for more information
- Added new exists() Function that only takes in 1 parameter, the key, this function returns a boolean value
- Added new values() Function that returns a SimpleVector of all the values in the Hashtable
- Added function comments.
- Emergency Patch: Fixed an issue where the Constructor wasnt properly overloaded.
- Adjusted Library Keywords
- Added new getElement() Function that returns an element at a specific index in the Hashtable
- Added New getKey() Function for Iterator
- Added New getValue() Function for Iterator
- Added New find() Function for Iterator.
- RESOLVED ISSUE: Iterator Iterates out of bounds (Issue #85)
- RESOLVED ISSUE: Resizing corrupts data in hashtable (Issue #81)
- RESOLVED ISSUE: get() and getElement() returning incorrectly (Issue #82)
- Added new operator[] function that allows you to access elements by index in the Hashtable
- Added new getBucket() function that returns the bucket at a specific index in the Hashtable
- Added new getBucketSize() function that returns the size of a bucket at a specific index in the Hashtable
- Added new debugIterator() function that iterates the table and prints out the [key, value] pairs.
- Adjusted Iterator operator* function. [FROM THIS]
KeyValuePair operator*() const {
return KeyValuePair{currentEntry->key, currentEntry->value};
}[TO THIS]
KeyValuePair operator*() const {
if (!currentEntry) {
return KeyValuePair{"", ""}; // Return an empty key-value pair if invalid
}
return KeyValuePair{currentEntry->key, currentEntry->value};
}This is to make sure that empty data is printed as empty and not garbage data.
- Adjusted begin() function to return end() instead of
return Iterator(this, TABLE_SIZE, nullptr);which is exactly what end() already has inside. This is just to be neater.
- Removed unnecessary print statements left behind from testing.
- Update is being used to properly progress Arduino Library Manager to next available version due to an error in last update creation.
- No other changes made.
Here's an example of how to use the Hashtable class:
#include <Hashtable.h>
#include <Arduino.h> // IF YOU ARE USING ARDUNINO's IDE, IGNORE THIS LINE
int main() {
Hashtable<int, String> dictionary;
// Add key-value pairs to the hash table
dictionary.put(1, "One");
dictionary.put(2, "Two");
dictionary.put(3, "Three");
// Retrieve values using keys
String value = dictionary.getElement(2);
Serial.println("Value for key 2: " + value);
//Another way of retrieving values using keys
String* value = dictionary.get(3);
if (value != nullptr) {
Serial.println("Value of key1: " + *value);
} else {
Serial.println("Key1 not found");
}
// Remove a key-value pair
dictionary.remove(1);
// Check if the hash table is empty
if (dictionary.isEmpty()) {
Serial.println("Hash table is empty.");
} else {
Serial.println("Hash table is not empty." );
}
// Iterate through the keys
for (auto it = dictionary.begin(); it != dictionary.end(); ++it) {
auto kv = *it;
Serial.print("Iterator output: Key: ");
Serial.print(kv.key);
Serial.print(", Value: ");
Serial.println(kv.value);
}
//inbuilt iterator/debug tool
dictionary.debugIterator();
//Verify Bucket Data
void debugTable() {
for (int i = 0; i < dictionary.bucketCount(); ++i) {
Serial.print("Bucket ");
Serial.print(i);
Serial.print(": ");
auto entry = dictionary.getBucket(i); // Use a method to get the bucket by index
while (entry != nullptr) {
Serial.print(entry->key + " -> " + entry->value + ", ");
entry = entry->next;
}
Serial.println();
}
}
}