diff --git a/Uebung 4/Uebung4_2/hashTable.cpp b/Uebung 4/Uebung4_2/hashTable.cpp new file mode 100644 index 0000000..98294ee --- /dev/null +++ b/Uebung 4/Uebung4_2/hashTable.cpp @@ -0,0 +1,135 @@ +#include "hashTable.h" +#include + +HashTable::HashTable() { + this->size = 0; + this->entries = nullptr; + this->setHashFunction("lastNumber"); +} + +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; + } 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; + inserted = true; + } + i = (i + 1) % this->size; + } + } +} + +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 < 4; i++) { + if(this->availableAlgorithms[i].name == algorithmName) { + this->hashFunction = this->availableAlgorithms[i].algorithm; + this->size = this->availableAlgorithms[i].size; + if(this->entries != nullptr) { + delete[] this->entries; + } + this->entries = new HashNode[this->size]; + 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; + return true; + } else { + return false; + } +} + + + +/* 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); +} + diff --git a/Uebung 4/Uebung4_2/hashTable.h b/Uebung 4/Uebung4_2/hashTable.h new file mode 100644 index 0000000..1d043b0 --- /dev/null +++ b/Uebung 4/Uebung4_2/hashTable.h @@ -0,0 +1,44 @@ +#include +#include "pbEntry.h" + +#pragma once +typedef int (*hashFunctionPtr)(std::string); // typedefinition of a pointer for a hashfunction; they all need conform to the guideline: int (std::string ) +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 + +class HashTable { + private: + class HashFunction { // private inner class to make hash functions managable + public: + int size; + std::string name; + 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}}; + + 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: + int size; // m in lecture + int numberOfEntries; // n in lecture + HashNode* entries; // nodes of the hash table + hashFunctionPtr hashFunction; // pointer to the hash algorithm used is stored in a private variable of type hashFunctionPtr - see beginning of this file + + + void insert(PbEntry* entry); + const PbEntry* search(std::string key); + bool deleteItem(std::string key); + void print(); + void setHashFunction(std::string name); + + HashTable(); // default constructor +}; \ No newline at end of file diff --git a/Uebung 4/Uebung4_2/main.cpp b/Uebung 4/Uebung4_2/main.cpp new file mode 100644 index 0000000..dcf1ec0 --- /dev/null +++ b/Uebung 4/Uebung4_2/main.cpp @@ -0,0 +1,35 @@ +#include "hashTable.h" +#include "pbEntry.h" +#include +#include + +int main() { + PbEntry entry1("3277971", "Norma Noe", "North Lyme Drive 30"); + PbEntry entry2("9928657", "Ashok Kumar", "Lawrence Avenue 24"); + PbEntry entry3("1674792", "Baby Doe", "North Lyme Street 34"); + PbEntry entry4("4991459", "Brett Boe", "North Lyme Road 35 "); + PbEntry entry5("1990539", "Carla Coe", "Lawrence Road 29"); + HashTable ht; + ht.insert(&entry1); + ht.insert(&entry2); + ht.insert(&entry3); + ht.insert(&entry4); + ht.insert(&entry5); + ht.print(); + + // ht.setHashFunction("mod17"); + // ht.insert(&entry1); + // ht.insert(&entry2); + // ht.insert(&entry3); + // ht.insert(&entry4); + // ht.insert(&entry5); + // ht.print(); + + // const PbEntry* s1 = ht.search("3277971"); + // std::cout << s1->toString(); + + // bool test = ht.deleteItem("3277971"); + // std::cout << test << std::endl; + // bool test2 = ht.deleteItem("3277971"); + // std::cout << test2 << std::endl; +} diff --git a/Uebung 4/Uebung4_2/makefile b/Uebung 4/Uebung4_2/makefile new file mode 100644 index 0000000..29eaeff --- /dev/null +++ b/Uebung 4/Uebung4_2/makefile @@ -0,0 +1,14 @@ +CC = g++ +FLAGS = -I +OBJECT_FILES = main.o pbEntry.o hashTable.o + +all: main + +clean: + rm -rf main main.exe *.o + +%.o: %.c $(DEPENDENCIES) + $(CC) -o $@ $< $(FLAGS). + +main: $(OBJECT_FILES) + $(CC) -o $@ $^ $(FLAGS). \ No newline at end of file diff --git a/Uebung 4/Uebung4_2/pbEntry.cpp b/Uebung 4/Uebung4_2/pbEntry.cpp new file mode 100644 index 0000000..e263d94 --- /dev/null +++ b/Uebung 4/Uebung4_2/pbEntry.cpp @@ -0,0 +1,17 @@ +#include "pbEntry.h" +#include + +PbEntry::PbEntry(std::string telephoneNumber, std::string name, std::string address) { + this->name = name; + this->address = address; + this->telephoneNumber = telephoneNumber; +} + +std::string PbEntry::toString() const { + std::stringstream s; + s << "Telephone number " << this->telephoneNumber << std::endl;; + s << "\tName: " << this->name <<"." << std::endl; + s << "\tAddress: " << this->address <<"." << std::endl; + + return s.str(); +} \ No newline at end of file diff --git a/Uebung 4/Uebung4_2/pbEntry.h b/Uebung 4/Uebung4_2/pbEntry.h new file mode 100644 index 0000000..1ffd4b2 --- /dev/null +++ b/Uebung 4/Uebung4_2/pbEntry.h @@ -0,0 +1,20 @@ +#include + + +#pragma once +/* -- */ +// Class PbEntry consisting of a person's name, his/her address and their telephone number +/* -- */ + + +class PbEntry { + public: + std::string name; + std::string address; + std::string telephoneNumber; + + PbEntry(std::string telephoneNumber, std::string name, std::string address); // Constructor with params for easier use + PbEntry() = delete; + + std::string toString() const; +}; \ No newline at end of file