#include "hashTableDynamic.h" #include HashTable::HashTable() { this->size = 0; this->entries = nullptr; this->setHashFunction("mod17"); this->numberOfEntries = 0; } HashTable::HashFunction::HashFunction(std::string name, hashFunctionPtr algorithm, int size) { this->name = name; this->algorithm = algorithm; this->size = size; } void HashTable::insert(PbEntry *entry) { int hashValue = this->hashFunction(entry->telephoneNumber); hashValue = hashValue % this->size; if (this->entries[hashValue].key == "" || this->entries[hashValue].key == "deleted") { this->entries[hashValue].key = entry->telephoneNumber; this->entries[hashValue].phonebookEntry = entry; this->numberOfEntries++; } else { bool inserted = false; int i = (hashValue + 1) % this->size; while (inserted == false) { if (i == hashValue) { std::cout << "HashTable full!" << std::endl; return; } if (this->entries[i].key == "" || this->entries[i].key == "deleted") { this->entries[i].key = entry->telephoneNumber; this->entries[i].phonebookEntry = entry; this->numberOfEntries++; inserted = true; } i = (i + 1) % this->size; } } std::cout << "Number of current Entries: " << this->numberOfEntries << ", LoadFactor: " << this->getloadFactor() << std::endl; if (this->getloadFactor() > 2.0 / 3.0) { if (this->size <= 17) { std::cout << "Upgrading to mod37" << std::endl; this->setHashFunction("mod37"); } else if (this->size <= 37) { std::cout << "Upgrading to mod71!" << std::endl; this->setHashFunction("mod71"); } else { std::cout << "Cannot upgrade further. Desastrous Failure imminent!!" << std::endl; if (this->numberOfEntries == this->size) { std::cout << "Could not insert. Hashtable is full and can not be expanded" << std::endl; return; } } } } void HashTable::print() { std::cout << "=====================================" << std::endl; for (int i = 0; i < this->size; i++) { std::cout << i << " :\t" << this->entries[i].key << std::endl; } std::cout << "=====================================" << std::endl; } void HashTable::setHashFunction(std::string algorithmName) { for (int i = 0; i < 6; i++) { if (this->availableAlgorithms[i].name == algorithmName) { HashNode *oldEntries = this->entries; int oldsize = this->size; this->hashFunction = this->availableAlgorithms[i].algorithm; this->size = this->availableAlgorithms[i].size; this->numberOfEntries = 0; this->entries = new HashNode[this->size]; if (oldEntries != nullptr) { for (int i = 0; i < oldsize; i++) { if (oldEntries[i].phonebookEntry != nullptr) { this->insert(oldEntries[i].phonebookEntry); } } delete[] oldEntries; } return; } } std::cerr << "The Hash Function provided was not found!" << std::endl; } const PbEntry *HashTable::search(std::string key) { int hashValue = this->hashFunction( key); // key is "hashed" and stored in the variable int hashValue hashValue = hashValue % this->size; int i = 0; while (this->entries[hashValue].key != key && this->entries[hashValue].key != "" && i <= this->size) { hashValue = (hashValue + 1) % this->size; i++; } if (this->entries[hashValue].key == key) { return this->entries[hashValue].phonebookEntry; } else { std::cout << "Entry with telephone number " << key << " not found!" << std::endl; return nullptr; } } bool HashTable::deleteItem(std::string key) { int hashValue = this->hashFunction(key); hashValue = hashValue % this->size; while (this->entries[hashValue].key != key && this->entries[hashValue].key != "") { hashValue = (hashValue + 1) % this->size; } if (this->entries[hashValue].key == key) { this->entries[hashValue].key = "deleted"; this->entries[hashValue].phonebookEntry = nullptr; delete this->entries[hashValue].phonebookEntry; this->numberOfEntries--; return true; } else { return false; } } float HashTable::getloadFactor() { return (float)this->numberOfEntries / this->size; } /* algorithm that "hashes" the last digit of a number */ int lastNumber(std::string telNr) { if (telNr.length() <= 0) { std::cerr << "Number '" << telNr << "' does not contain enough digits. At least 1 needed!"; exit(1); } return std::stoi(std::string(telNr.end() - 1, telNr.end())); } /* algorithm that "hashes" the first three digits of a number */ int firstThreeNumbers(std::string telNr) { if (telNr.length() < 3) { std::cerr << "Number '" << telNr << "' does not contain enough digits. At least 3 needed!"; exit(1); } return std::stoi(std::string(telNr.begin(), telNr.begin() + 3)); } /* algorithm that "hashes" the last three digits of a number */ int lastThreeNumbers(std::string telNr) { if (telNr.length() < 3) { std::cerr << "Number '" << telNr << "' does not contain enough digits. At least 3 needed!"; exit(1); } return std::stoi(std::string(telNr.end() - 3, telNr.end())); } /* algorithm that "hashes" the through mod17 */ int mod17(std::string telNr) { return (int)(std::stol(telNr) % 17); } /* algorithm that "hashes" the through mod37 */ int mod37(std::string telNr) { return (int)(std::stol(telNr) % 37); } /* algorithm that "hashes" the through mod71 */ int mod71(std::string telNr) { return (int)(std::stol(telNr) % 71); }