/** * Lisa Dion * CS 2240 * 2020-Oct-28 * * Clayton Cafiero * 2021-Jan-17 * - Expanded comments to include explanation of optional * - Eliminated unnecessary `using` * - Eliminated built-in hash function and require passing in * of hash function upon instantiation * - Added getter for tableSize * - Other minor changes */ #ifndef HASHTABLE_H #define HASHTABLE_H /** * We want `` so we can use in our hash table, * i.e. some elements have values, others do not, hence * `nullopt`. We've been using C++ 14 standard so far for * this class, and optional was introduced in C++ 17. * So here we try to include if * standard is < 17, if that fails we go with C++ version * * * If this produces errors, go into CMakeLists.txt and change * the CMAKE_CXX_STANDARD from 14 to 17. * * Here also is a valid use case for `using` in a header * file. We want `optional`, `nullopt`, and `make_optional`, * but these reside in different scopes in C++ 14 vs C++ 17. * Hence we apply `using` here, so that the code in our * header is portable between 14 and 17. Notice that we don't * use the entire namespace, just what we actually use. */ #if __cplusplus < 17 #include using std::experimental::optional; using std::experimental::nullopt; using std::experimental::make_optional; #else #include using std::optional; using std::nullopt; using std::make_optional; #endif #include #include #include #include template class HashTable { private: // The vector can contain Hashable types or nullopt. // nullopt indicates that an element is in an uninitialized // state. std::vector> table; unsigned long tableSize; // Store the function that gets the string key from the Hashable std::function getKey; // Store the hash function to be used std::function hashFunc; public: // Constructor HashTable(unsigned long tableSize, std::function getKey, std::function hashFunc) { this->tableSize = tableSize; this->getKey = getKey; this->hashFunc = hashFunc; // Make the vector the size of tableSize table.resize(tableSize); } // insert (without collision handling) void insert(Hashable item) { // Get the key from the item std::string key = getKey(item); // Hash the key to get an index unsigned long index = hashFunc(key, tableSize); // Put the item at that spot in the vector table[index] = item; } // find // Return type is optional Hashable because if we find the item, // we return it; otherwise, we return nullopt. optional find(std::string key) { unsigned long index = hashFunc(key, tableSize); // Check that there is an item at that index if (table[index]) { // Check if it's the item we're looking for if (key == getKey(*table[index])) { // We found the item return *table[index]; } } // We did not find the item return nullopt; } // delete optional remove(std::string key) { unsigned long index = hashFunc(key, tableSize); // Check that there is an item at that index if (table[index]) { // Check if it's the item we're looking for if (key == getKey(*table[index])) { // We found the item. Delete it. Hashable returnItem = *table[index]; table[index] = nullopt; return returnItem; } } // We did not find the item return nullopt; } // Getter for table size int getTableSize() const { return tableSize; } // print the table void printTable() const { for (int i = 0; i < tableSize; ++i) { std::cout << i << ": "; // If the index of the table has a value if (table[i]) { // Access the value with * and print it out std::cout << *table[i]; } std::cout << std::endl; } } }; #endif // HASHTABLE_H