This commit is contained in:
Samuel Oberhofer 2022-06-18 17:04:24 +02:00
parent 8737713cd9
commit 73b9c1a8af
3 changed files with 237 additions and 153 deletions

View File

@ -2,134 +2,180 @@
#include <iostream> #include <iostream>
HashTable::HashTable() { HashTable::HashTable() {
this->size = 0; this->size = 0;
this->entries = nullptr; this->entries = nullptr;
this->setHashFunction("lastNumber"); this->setHashFunction("mod17");
this->numberOfEntries = 0;
} }
HashTable::HashFunction::HashFunction(std::string name, hashFunctionPtr algorithm, int size) { HashTable::HashFunction::HashFunction(std::string name,
this->name = name; hashFunctionPtr algorithm, int size) {
this->algorithm = algorithm; this->name = name;
this->size = size; this->algorithm = algorithm;
this->size = size;
} }
void HashTable::insert(PbEntry *entry) {
int hashValue = this->hashFunction(entry->telephoneNumber);
hashValue = hashValue % this->size;
void HashTable::insert(PbEntry* entry) { if (this->entries[hashValue].key == "" ||
int hashValue = this->hashFunction(entry->telephoneNumber); this->entries[hashValue].key == "deleted") {
hashValue = hashValue % this->size; this->entries[hashValue].key = entry->telephoneNumber;
this->entries[hashValue].phonebookEntry = entry;
if(this->entries[hashValue].key == "" || this->entries[hashValue].key == "deleted") { this->numberOfEntries++;
this->entries[hashValue].key = entry->telephoneNumber; } else {
this->entries[hashValue].phonebookEntry = entry; bool inserted = false;
} else { int i = (hashValue + 1) % this->size;
bool inserted = false; while (inserted == false) {
int i = (hashValue + 1) % this->size; if (i == hashValue) {
while(inserted == false) { std::cout << "HashTable full!" << std::endl;
if(i == hashValue) { return;
std::cout << "HashTable full!" << std::endl; }
return; if (this->entries[i].key == "" || this->entries[i].key == "deleted") {
} this->entries[i].key = entry->telephoneNumber;
if(this->entries[i].key == "" || this->entries[i].key == "deleted") { this->entries[i].phonebookEntry = entry;
this->entries[i].key = entry->telephoneNumber; this->numberOfEntries++;
this->entries[i].phonebookEntry = entry; inserted = true;
inserted = true; }
} i = (i + 1) % this->size;
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() { void HashTable::print() {
std::cout << "=====================================" << std::endl; std::cout << "=====================================" << std::endl;
for(int i = 0; i < this->size; i++) { for (int i = 0; i < this->size; i++) {
std::cout << i << " :\t" << this->entries[i].key << std::endl; std::cout << i << " :\t" << this->entries[i].key << std::endl;
}
} std::cout << "=====================================" << std::endl;
std::cout << "=====================================" << std::endl;
} }
void HashTable::setHashFunction(std::string algorithmName) { void HashTable::setHashFunction(std::string algorithmName) {
for(int i = 0; i < 4; i++) { for (int i = 0; i < 6; i++) {
if(this->availableAlgorithms[i].name == algorithmName) { if (this->availableAlgorithms[i].name == algorithmName) {
this->hashFunction = this->availableAlgorithms[i].algorithm; HashNode *oldEntries = this->entries;
this->size = this->availableAlgorithms[i].size; int oldsize = this->size;
if(this->entries != nullptr) { this->hashFunction = this->availableAlgorithms[i].algorithm;
delete[] this->entries; this->size = this->availableAlgorithms[i].size;
} this->numberOfEntries = 0;
this->entries = new HashNode[this->size]; this->entries = new HashNode[this->size];
return; if (oldEntries != nullptr) {
} for (int i = 0; i < oldsize; i++) {
} if (oldEntries[i].phonebookEntry != nullptr) {
std::cerr << "The Hash Function provided was not found!" << std::endl; 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) { const PbEntry *HashTable::search(std::string key) {
int hashValue = this->hashFunction(key); // key is "hashed" and stored in the variable int hashValue int hashValue = this->hashFunction(
hashValue = hashValue % this->size; key); // key is "hashed" and stored in the variable int hashValue
int i = 0; hashValue = hashValue % this->size;
while(this->entries[hashValue].key != key && this->entries[hashValue].key != "" && i <= this->size) { int i = 0;
hashValue = (hashValue + 1) % this->size; while (this->entries[hashValue].key != key &&
i++; this->entries[hashValue].key != "" && i <= this->size) {
} hashValue = (hashValue + 1) % this->size;
i++;
}
if(this->entries[hashValue].key == key) { if (this->entries[hashValue].key == key) {
return this->entries[hashValue].phonebookEntry; return this->entries[hashValue].phonebookEntry;
} else { } else {
std::cout << "Entry with telephone number " << key << " not found!" << std::endl; std::cout << "Entry with telephone number " << key << " not found!"
return nullptr; << std::endl;
} return nullptr;
}
} }
bool HashTable::deleteItem(std::string key) { bool HashTable::deleteItem(std::string key) {
int hashValue = this->hashFunction(key); int hashValue = this->hashFunction(key);
hashValue = hashValue % this->size; hashValue = hashValue % this->size;
while(this->entries[hashValue].key != key && this->entries[hashValue].key != "") { while (this->entries[hashValue].key != key &&
hashValue = (hashValue + 1) % this->size; this->entries[hashValue].key != "") {
} hashValue = (hashValue + 1) % this->size;
}
if(this->entries[hashValue].key == key) { if (this->entries[hashValue].key == key) {
this->entries[hashValue].key = "deleted"; this->entries[hashValue].key = "deleted";
this->entries[hashValue].phonebookEntry = nullptr; this->entries[hashValue].phonebookEntry = nullptr;
delete this->entries[hashValue].phonebookEntry; delete this->entries[hashValue].phonebookEntry;
return true; this->numberOfEntries--;
} else {
return false; return true;
} } else {
return false;
}
} }
float HashTable::getloadFactor() {
return (float)this->numberOfEntries / this->size;
}
/* algorithm that "hashes" the last digit of a number */ /* algorithm that "hashes" the last digit of a number */
int lastNumber(std::string telNr) { int lastNumber(std::string telNr) {
if(telNr.length() <=0) { if (telNr.length() <= 0) {
std::cerr << "Number '" << telNr << "' does not contain enough digits. At least 1 needed!"; std::cerr << "Number '" << telNr
exit(1); << "' does not contain enough digits. At least 1 needed!";
} exit(1);
return std::stoi(std::string(telNr.end()-1, telNr.end())); }
return std::stoi(std::string(telNr.end() - 1, telNr.end()));
} }
/* algorithm that "hashes" the first three digits of a number */ /* algorithm that "hashes" the first three digits of a number */
int firstThreeNumbers(std::string telNr) { int firstThreeNumbers(std::string telNr) {
if(telNr.length() < 3) { if (telNr.length() < 3) {
std::cerr << "Number '" << telNr << "' does not contain enough digits. At least 3 needed!"; std::cerr << "Number '" << telNr
exit(1); << "' does not contain enough digits. At least 3 needed!";
} exit(1);
return std::stoi(std::string(telNr.begin(), telNr.begin()+3)); }
return std::stoi(std::string(telNr.begin(), telNr.begin() + 3));
} }
/* algorithm that "hashes" the last three digits of a number */ /* algorithm that "hashes" the last three digits of a number */
int lastThreeNumbers(std::string telNr) { int lastThreeNumbers(std::string telNr) {
if(telNr.length() < 3) { if (telNr.length() < 3) {
std::cerr << "Number '" << telNr << "' does not contain enough digits. At least 3 needed!"; std::cerr << "Number '" << telNr
exit(1); << "' does not contain enough digits. At least 3 needed!";
} exit(1);
return std::stoi(std::string(telNr.end()-3, telNr.end())); }
return std::stoi(std::string(telNr.end() - 3, telNr.end()));
} }
/* algorithm that "hashes" the through mod17 */ /* algorithm that "hashes" the through mod17 */
int mod17(std::string telNr) { int mod17(std::string telNr) { return (int)(std::stol(telNr) % 17); }
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); }

View File

@ -1,44 +1,65 @@
#include <string>
#include "pbEntry.h" #include "pbEntry.h"
#include <string>
#pragma once #pragma once
typedef int (*hashFunctionPtr)(std::string); // typedefinition of a pointer for a hashfunction; they all need conform to the guideline: int <functionName>(std::string <param>) typedef int (*hashFunctionPtr)(
int lastNumber(std::string telNr); // hash algorithm that uses only the last digit of a given telNr std::string); // typedefinition of a pointer for a hashfunction; they all
int firstThreeNumbers(std::string telNr); // hash algorithm that uses the first three digits of a given telNr // need conform to the guideline: int
int lastThreeNumbers(std::string telNr); // hash algorithm that uses the last three digits of a given telNr // <functionName>(std::string <param>)
int mod17(std::string telNr); // hash algorithm that takes a given telNr mod17 int lastNumber(std::string telNr); // hash algorithm that uses only the last
// digit of a given telNr
int firstThreeNumbers(std::string telNr); // hash algorithm that uses the first
// three digits of a given telNr
int lastThreeNumbers(std::string telNr); // hash algorithm that uses the last
// three digits of a given telNr
int mod17(std::string telNr); // hash algorithm that takes a given telNr mod17
int mod37(std::string telNr); // hash algorithm that takes a given telNr mod37
int mod71(std::string telNr); // hash algorithm that takes a given telNr mod71
class HashTable { class HashTable {
private: private:
class HashFunction { // private inner class to make hash functions managable class HashFunction { // private inner class to make hash functions managable
public: public:
int size; int size;
std::string name; std::string name;
hashFunctionPtr algorithm; hashFunctionPtr algorithm;
HashFunction(std::string name, hashFunctionPtr algorithm, int size); // constructor
};
HashFunction availableAlgorithms[4] = { {"lastNumber", lastNumber, 10}, {"firstThreeNumbers", firstThreeNumbers, 1000}, {"lastThreeNumbers", lastThreeNumbers, 1000}, {"mod17", mod17, 17}}; HashFunction(std::string name, hashFunctionPtr algorithm,
int size); // constructor
class HashNode { // private inner class for HashNodes that have a key (which will be the telephone number) and a value of type PbEntry };
public:
std::string key = "";
PbEntry* phonebookEntry;
};
public: HashFunction availableAlgorithms[6] = {
int size; // m in lecture {"lastNumber", lastNumber, 10},
int numberOfEntries; // n in lecture {"firstThreeNumbers", firstThreeNumbers, 1000},
HashNode* entries; // nodes of the hash table {"lastThreeNumbers", lastThreeNumbers, 1000},
hashFunctionPtr hashFunction; // pointer to the hash algorithm used is stored in a private variable of type hashFunctionPtr - see beginning of this file {"mod17", mod17, 17},
{"mod37", mod37, 37},
{"mod71", mod71, 71}};
class HashNode { // private inner class for HashNodes that have a key (which
// will be the telephone number) and a value of type PbEntry
public:
std::string key = "";
PbEntry *phonebookEntry;
HashNode() : key(""), phonebookEntry(nullptr) {}
};
void insert(PbEntry* entry); public:
const PbEntry* search(std::string key); int size; // m in lecture
bool deleteItem(std::string key); int numberOfEntries; // n in lecture
void print(); HashNode *entries; // nodes of the hash table
void setHashFunction(std::string name); hashFunctionPtr hashFunction; // pointer to the hash algorithm used is stored
// in a private variable of type
// hashFunctionPtr - see beginning of this file
HashTable(); // default constructor void insert(PbEntry *entry);
const PbEntry *search(std::string key);
bool deleteItem(std::string key);
void print();
void setHashFunction(std::string name);
float getloadFactor();
HashTable(); // default constructor
}; };

View File

@ -1,35 +1,52 @@
#include "hashTable.h" #include "hashTable.h"
#include "pbEntry.h" #include "pbEntry.h"
#include <string>
#include <iostream> #include <iostream>
#include <string>
// Function to generate random strings for our Wares. See:
// https://stackoverflow.com/a/12468109
std::string random_string(size_t length) {
auto randchar = []() -> char {
const char charset[] = "0123456789";
const size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
}
int main() { int main() {
PbEntry entry1("3277971", "Norma Noe", "North Lyme Drive 30"); PbEntry entry1("3277971", "Norma Noe", "North Lyme Drive 30");
PbEntry entry2("9928657", "Ashok Kumar", "Lawrence Avenue 24"); PbEntry entry2("9928657", "Ashok Kumar", "Lawrence Avenue 24");
PbEntry entry3("1674792", "Baby Doe", "North Lyme Street 34"); PbEntry entry3("1674792", "Baby Doe", "North Lyme Street 34");
PbEntry entry4("4991459", "Brett Boe", "North Lyme Road 35 "); PbEntry entry4("4991459", "Brett Boe", "North Lyme Road 35 ");
PbEntry entry5("1990539", "Carla Coe", "Lawrence Road 29"); PbEntry entry5("1990539", "Carla Coe", "Lawrence Road 29");
HashTable ht; HashTable ht;
ht.insert(&entry1); ht.insert(&entry1);
ht.insert(&entry2); ht.insert(&entry2);
ht.insert(&entry3); ht.insert(&entry3);
ht.insert(&entry4); ht.insert(&entry4);
ht.insert(&entry5); ht.insert(&entry5);
ht.print(); for (int i = 0; i < 60; i++) {
ht.insert(new PbEntry(random_string(7), "test", "test"));
}
ht.print();
std::cout << ht.getloadFactor() << std::endl;
// ht.setHashFunction("mod17"); // ht.setHashFunction("mod17");
// ht.insert(&entry1); // ht.insert(&entry1);
// ht.insert(&entry2); // ht.insert(&entry2);
// ht.insert(&entry3); // ht.insert(&entry3);
// ht.insert(&entry4); // ht.insert(&entry4);
// ht.insert(&entry5); // ht.insert(&entry5);
// ht.print(); // ht.print();
// const PbEntry* s1 = ht.search("3277971"); // const PbEntry* s1 = ht.search("3277971");
// std::cout << s1->toString(); // std::cout << s1->toString();
// bool test = ht.deleteItem("3277971"); // bool test = ht.deleteItem("3277971");
// std::cout << test << std::endl; // std::cout << test << std::endl;
// bool test2 = ht.deleteItem("3277971"); // bool test2 = ht.deleteItem("3277971");
// std::cout << test2 << std::endl; // std::cout << test2 << std::endl;
} }