From 1e648fc1d2187f9391ac458d1a6d1fc000f3c95d Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 17:25:16 -0400 Subject: [PATCH 01/21] added hashing to cmake --- CMakeLists.txt | 1 + hashing/CMakeLists.txt | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 hashing/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index d7fa88559..bfaeccdbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ add_subdirectory(math) add_subdirectory(others) add_subdirectory(search) add_subdirectory(ciphers) +add_subdirectory(hashing) add_subdirectory(strings) add_subdirectory(sorting) add_subdirectory(geometry) diff --git a/hashing/CMakeLists.txt b/hashing/CMakeLists.txt new file mode 100644 index 000000000..d8bad16c1 --- /dev/null +++ b/hashing/CMakeLists.txt @@ -0,0 +1,18 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. RELATIVE may makes it easier to extract an executable name +# automatically. +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp ) +# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c ) +# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) +foreach( testsourcefile ${APP_SOURCES} ) + # I used a simple string replace, to cut off .cpp. + string( REPLACE ".cpp" "" testname ${testsourcefile} ) + add_executable( ${testname} ${testsourcefile} ) + + set_target_properties(${testname} PROPERTIES LINKER_LANGUAGE CXX) + if(OpenMP_CXX_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_CXX) + endif() + install(TARGETS ${testname} DESTINATION "bin/hash") + +endforeach( testsourcefile ${APP_SOURCES} ) From 7ae91d260739b28b9ae3cc52dc05e0fd2fc43077 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 17:25:44 -0400 Subject: [PATCH 02/21] fix chaining --- hashing/chaining.cpp | 232 ++++++++++++++++++++++++++----------------- 1 file changed, 142 insertions(+), 90 deletions(-) diff --git a/hashing/chaining.cpp b/hashing/chaining.cpp index 6afd2d13b..ea4720475 100644 --- a/hashing/chaining.cpp +++ b/hashing/chaining.cpp @@ -1,110 +1,162 @@ -#include +/** + * @file chaining.cpp + * @author [vasutomar](https://github.com/vasutomar) + * @author [Krishna Vedala](https://github.com/kvedala) + * @brief + */ +#include #include -using namespace std; +#include +#include +namespace { // keep the code local to this file by assigning them to an unnamed + // namespace +/** + * @{ + * @brief Define a linked node + */ struct Node { - int data; - struct Node *next; -} * head[100], *curr; + int data{}; ///< data stored in the node + std::shared_ptr next; ///< pointer to the next node +}; -void init() { - for (int i = 0; i < 100; i++) head[i] = NULL; -} +/** + * @brief Chain class with a given modulus + */ +class chain { + private: + std::vector> head; ///< array of nodes + int _mod; ///< modulus of the class -void add(int x, int h) { - struct Node *temp = new Node; - temp->data = x; - temp->next = NULL; - if (!head[h]) { - head[h] = temp; - curr = head[h]; - } else { - curr = head[h]; - while (curr->next) curr = curr->next; - curr->next = temp; + public: + /** + * @brief Construct a new chain object + * + * @param mod modulus of the chain + */ + chain(int mod) : _mod(mod) { + while (mod--) head.push_back(nullptr); } -} -void display(int mod) { - struct Node *temp; - int i; - for (i = 0; i < mod; i++) { - if (!head[i]) { - cout << "Key " << i << " is empty" << endl; + /** + * @brief create and add a new node with a give value and at a given height + * + * @param x value at the new node + * @param h height of the node + */ + void add(int x, int h) { + std::shared_ptr curr; + std::shared_ptr temp(new struct Node); + temp->data = x; + temp->next = nullptr; + if (!head[h]) { + head[h] = temp; + curr = head[h]; } else { - cout << "Key " << i << " has values = "; - temp = head[i]; - while (temp->next) { - cout << temp->data << " "; - temp = temp->next; - } - cout << temp->data; - cout << endl; + curr = head[h]; + while (curr->next) curr = curr->next; + curr->next = temp; } } -} -int hash(int x, int mod) { return x % mod; } - -void find(int x, int h) { - struct Node *temp = head[h]; - if (!head[h]) { - cout << "Element not found"; - return; + /** + * @brief Display the chain + */ + void display() { + std::shared_ptr temp = nullptr; + int i = 0; + for (i = 0; i < _mod; i++) { + if (!head[i]) { + std::cout << "Key " << i << " is empty" << std::endl; + } else { + std::cout << "Key " << i << " has values = "; + temp = head[i]; + while (temp->next) { + std::cout << temp->data << " "; + temp = temp->next; + } + std::cout << temp->data; + std::cout << std::endl; + } + } } - while (temp->data != x && temp->next) temp = temp->next; - if (temp->next) - cout << "Element found"; - else { - if (temp->data == x) - cout << "Element found"; - else - cout << "Element not found"; - } -} -int main(void) { - init(); - int c, x, mod, h; - cout << "Enter the size of Hash Table. = "; - cin >> mod; + /** + * @brief Compute the hash of a value for current chain + * + * @param x value to compute modulus of + * @return modulus of `x` + */ + int hash(int x) const { return x % _mod; } + + void find(int x, int h) { + auto temp = head[h]; + if (!head[h]) { + std::cout << "Element not found"; + return; + } + while (temp->data != x && temp->next) temp = temp->next; + if (temp->next) { + std::cout << "Element found"; + } else { + if (temp->data == x) { + std::cout << "Element found"; + } else { + std::cout << "Element not found"; + } + } + } +}; + +} // namespace + +/** Main function + * @returns `0` always + */ +int main() { + int c = 0, x = 0, mod = 0, h = 0; + std::cout << "Enter the size of Hash Table. = "; + std::cin >> mod; + + chain mychain(mod); + bool loop = true; while (loop) { - cout << endl; - cout << "PLEASE CHOOSE -" << endl; - cout << "1. Add element." << endl; - cout << "2. Find element." << endl; - cout << "3. Generate Hash." << endl; - cout << "4. Display Hash table." << endl; - cout << "5. Exit." << endl; - cin >> c; + std::cout << std::endl; + std::cout << "PLEASE CHOOSE -" << std::endl; + std::cout << "1. Add element." << std::endl; + std::cout << "2. Find element." << std::endl; + std::cout << "3. Generate Hash." << std::endl; + std::cout << "4. Display Hash table." << std::endl; + std::cout << "5. Exit." << std::endl; + std::cin >> c; switch (c) { - case 1: - cout << "Enter element to add = "; - cin >> x; - h = hash(x, mod); - h = fabs(h); - add(x, h); - break; - case 2: - cout << "Enter element to search = "; - cin >> x; - h = hash(x, mod); - find(x, h); - break; - case 3: - cout << "Enter element to generate hash = "; - cin >> x; - cout << "Hash of " << x << " is = " << hash(x, mod); - break; - case 4: - display(mod); - break; - default: - loop = false; - break; + case 1: + std::cout << "Enter element to add = "; + std::cin >> x; + h = mychain.hash(x); + h = std::fabs(h); + mychain.add(x, h); + break; + case 2: + std::cout << "Enter element to search = "; + std::cin >> x; + h = mychain.hash(x); + mychain.find(x, h); + break; + case 3: + std::cout << "Enter element to generate hash = "; + std::cin >> x; + std::cout << "Hash of " << x << " is = " << mychain.hash(x); + break; + case 4: + mychain.display(); + break; + default: + loop = false; + break; } - cout << endl; + std::cout << std::endl; } /*add(1,&head1); add(2,&head1); From e45a37763d45aee267e92c8d29e89a7eaac5744e Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 17:28:45 -0400 Subject: [PATCH 03/21] fix absolute value --- hashing/chaining.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hashing/chaining.cpp b/hashing/chaining.cpp index ea4720475..0bc7df0eb 100644 --- a/hashing/chaining.cpp +++ b/hashing/chaining.cpp @@ -135,7 +135,7 @@ int main() { std::cout << "Enter element to add = "; std::cin >> x; h = mychain.hash(x); - h = std::fabs(h); + h = std::abs(h); mychain.add(x, h); break; case 2: From 8eddee9846616c72b74690d7e84aca1edcbd8846 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 17:31:13 -0400 Subject: [PATCH 04/21] fix file brief doc --- hashing/chaining.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hashing/chaining.cpp b/hashing/chaining.cpp index 0bc7df0eb..5f40b852b 100644 --- a/hashing/chaining.cpp +++ b/hashing/chaining.cpp @@ -2,7 +2,7 @@ * @file chaining.cpp * @author [vasutomar](https://github.com/vasutomar) * @author [Krishna Vedala](https://github.com/kvedala) - * @brief + * @brief Implementation of node chains accessed using keys. */ #include #include From e2a94da27f058e4238e8c72ead848559d85a0426 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 17:58:14 -0400 Subject: [PATCH 05/21] fix double_hash_... --- hashing/double_hash_hash_table.cpp | 122 ++++++++++++++++------------- 1 file changed, 68 insertions(+), 54 deletions(-) diff --git a/hashing/double_hash_hash_table.cpp b/hashing/double_hash_hash_table.cpp index 7ee2757de..26a1150a8 100644 --- a/hashing/double_hash_hash_table.cpp +++ b/hashing/double_hash_hash_table.cpp @@ -1,24 +1,31 @@ -// Copyright 2019 - -#include -#include +/** + * @file double_hash_hash_table.cpp + * @author [achance6](https://github.com/achance6) + * @author [Krishna Vedala](https://github.com/kvedala) + * @brief + */ #include +#include #include +#include using std::cin; using std::cout; using std::endl; using std::string; +namespace { // keep the code local to this file by assigning them to an unnamed + // namespace + // fwd declarations -struct Entry; +using Entry = struct Entry; bool putProber(Entry entry, int key); bool searchingProber(Entry entry, int key); void add(int key); // globals int notPresent; -struct Entry* table; +std::vector table; int totalSize; int tomb = -1; int size; @@ -37,19 +44,20 @@ int hashFxn(int key) { } // Used for second hash function -int otherHashFxn(int key) { +size_t otherHashFxn(int key) { std::hash hash; return 1 + (7 - (hash(key) % 7)); } // Performs double hashing to resolve collisions int doubleHash(int key, bool searching) { - int hash = static_cast(fabs(hashFxn(key))); + int hash = static_cast(std::abs(hashFxn(key))); int i = 0; Entry entry; do { - int index = static_cast(fabs((hash + (i * otherHashFxn(key))))) % - totalSize; + int index = + static_cast(std::abs((hash + (i * otherHashFxn(key))))) % + totalSize; entry = table[index]; if (searching) { if (entry.key == notPresent) { @@ -63,17 +71,19 @@ int doubleHash(int key, bool searching) { i++; } else { if (putProber(entry, key)) { - if (!rehashing) + if (!rehashing) { cout << "Spot found!" << endl; + } return index; } - if (!rehashing) + if (!rehashing) { cout << "Spot taken, looking at next (next index:" << " " << static_cast( - fabs((hash + (i * otherHashFxn(key))))) % + std::abs((hash + (i * otherHashFxn(key))))) % totalSize << ")" << endl; + } i++; } if (i == totalSize * 100) { @@ -94,8 +104,9 @@ bool putProber(Entry entry, int key) { // Looks for a matching key bool searchingProber(Entry entry, int key) { - if (entry.key == key) + if (entry.key == key) { return true; + } return false; } @@ -120,9 +131,9 @@ void rehash() { // Necessary so wall of add info isn't printed all at once rehashing = true; int oldSize = totalSize; - Entry* oldTable = table; + std::vector oldTable(table); // Really this should use the next prime number greater than totalSize * 2 - table = new Entry[totalSize * 2]; + table = std::vector(totalSize * 2); totalSize *= 2; for (int i = 0; i < oldSize; i++) { if (oldTable[i].key != -1 && oldTable[i].key != notPresent) { @@ -130,17 +141,19 @@ void rehash() { add(oldTable[i].key); } } - delete[] oldTable; + // delete[] oldTable; + // oldTable.reset(); + rehashing = false; cout << "Table was rehashed, new size is: " << totalSize << endl; } // Checks for load factor here void add(int key) { - Entry* entry = new Entry(); - entry->key = key; + // auto* entry = new Entry(); + // entry->key = key; int index = doubleHash(key, false); - table[index] = *entry; + table[index].key = key; // Load factor greater than 0.5 causes resizing if (++size / static_cast(totalSize) >= 0.5) { rehash(); @@ -164,7 +177,7 @@ void addInfo(int key) { display(); cout << endl; cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << fabs(hashFxn(key) % totalSize); + << " == " << std::abs(hashFxn(key) % totalSize); cout << endl; add(key); cout << "New table: "; @@ -183,13 +196,14 @@ void removalInfo(int key) { cout << "New table: "; display(); } +} // namespace // I/O -int main(void) { - int cmd, hash, key; +int main() { + int cmd = 0, hash = 0, key = 0; cout << "Enter the initial size of Hash Table. = "; cin >> totalSize; - table = new Entry[totalSize]; + table = std::vector(totalSize); bool loop = true; while (loop) { system("pause"); @@ -203,37 +217,37 @@ int main(void) { cout << "6. Exit." << endl; cin >> cmd; switch (cmd) { - case 1: - cout << "Enter key to add = "; - cin >> key; - addInfo(key); - break; - case 2: - cout << "Enter key to remove = "; - cin >> key; - removalInfo(key); - break; - case 3: { - cout << "Enter key to search = "; - cin >> key; - Entry entry = table[doubleHash(key, true)]; - if (entry.key == notPresent) { - cout << "Key not present"; + case 1: + cout << "Enter key to add = "; + cin >> key; + addInfo(key); + break; + case 2: + cout << "Enter key to remove = "; + cin >> key; + removalInfo(key); + break; + case 3: { + cout << "Enter key to search = "; + cin >> key; + Entry entry = table[doubleHash(key, true)]; + if (entry.key == notPresent) { + cout << "Key not present"; + } + break; } - break; - } - case 4: - cout << "Enter element to generate hash = "; - cin >> key; - cout << "Hash of " << key << " is = " << fabs(hashFxn(key)); - break; - case 5: - display(); - break; - default: - loop = false; - break; - delete[] table; + case 4: + cout << "Enter element to generate hash = "; + cin >> key; + cout << "Hash of " << key << " is = " << std::abs(hashFxn(key)); + break; + case 5: + display(); + break; + default: + loop = false; + break; + // delete[] table; } cout << endl; } From c81705eab65942934f9efcbb607b0b7c57e4c32d Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 18:05:43 -0400 Subject: [PATCH 06/21] remove std::abs as it is unecessary for size_t which is already unsigned --- hashing/double_hash_hash_table.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/hashing/double_hash_hash_table.cpp b/hashing/double_hash_hash_table.cpp index 26a1150a8..5a9615b35 100644 --- a/hashing/double_hash_hash_table.cpp +++ b/hashing/double_hash_hash_table.cpp @@ -38,7 +38,7 @@ struct Entry { }; // Hash a key -int hashFxn(int key) { +size_t hashFxn(int key) { std::hash hash; return hash(key); } @@ -51,13 +51,12 @@ size_t otherHashFxn(int key) { // Performs double hashing to resolve collisions int doubleHash(int key, bool searching) { - int hash = static_cast(std::abs(hashFxn(key))); + int hash = static_cast(hashFxn(key)); int i = 0; Entry entry; do { int index = - static_cast(std::abs((hash + (i * otherHashFxn(key))))) % - totalSize; + static_cast(hash + (i * otherHashFxn(key))) % totalSize; entry = table[index]; if (searching) { if (entry.key == notPresent) { @@ -79,8 +78,7 @@ int doubleHash(int key, bool searching) { if (!rehashing) { cout << "Spot taken, looking at next (next index:" << " " - << static_cast( - std::abs((hash + (i * otherHashFxn(key))))) % + << static_cast(hash + (i * otherHashFxn(key))) % totalSize << ")" << endl; } @@ -177,7 +175,7 @@ void addInfo(int key) { display(); cout << endl; cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << std::abs(hashFxn(key) % totalSize); + << " == " << hashFxn(key) % totalSize; cout << endl; add(key); cout << "New table: "; @@ -239,7 +237,7 @@ int main() { case 4: cout << "Enter element to generate hash = "; cin >> key; - cout << "Hash of " << key << " is = " << std::abs(hashFxn(key)); + cout << "Hash of " << key << " is = " << hashFxn(key); break; case 5: display(); From abfe9ad081fcf8eb986a13a89490275a4c8c72a2 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 23 Jul 2020 22:07:02 +0000 Subject: [PATCH 07/21] clang-tidy fixes for c81705eab65942934f9efcbb607b0b7c57e4c32d --- hashing/chaining.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hashing/chaining.cpp b/hashing/chaining.cpp index 5f40b852b..974b10584 100644 --- a/hashing/chaining.cpp +++ b/hashing/chaining.cpp @@ -34,7 +34,7 @@ class chain { * * @param mod modulus of the chain */ - chain(int mod) : _mod(mod) { + explicit chain(int mod) : _mod(mod) { while (mod--) head.push_back(nullptr); } From d955a49de9cff055887edfba89fa6e8bbe983321 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 18:16:56 -0400 Subject: [PATCH 08/21] fixed code fir linear_probing.... --- hashing/linear_probing_hash_table.cpp | 115 ++++++++++++++------------ 1 file changed, 62 insertions(+), 53 deletions(-) diff --git a/hashing/linear_probing_hash_table.cpp b/hashing/linear_probing_hash_table.cpp index 393504c1d..a125f016b 100644 --- a/hashing/linear_probing_hash_table.cpp +++ b/hashing/linear_probing_hash_table.cpp @@ -1,24 +1,30 @@ -// Copyright 2019 - -#include -#include +/** + * @file + * @author [achance6](https://github.com/achance6) + * @author [Krishna Vedala](https://github.com/kvedala) + * @brief + */ #include #include +#include using std::cin; using std::cout; using std::endl; using std::string; +namespace { // keep the code local to this file by assigning them to an unnamed + // namespace + // fwd declarations -struct Entry; +using Entry = struct Entry; bool putProber(Entry entry, int key); bool searchingProber(Entry entry, int key); void add(int key); // globals int notPresent; -struct Entry* table; +std::vector table; int totalSize; int tomb = -1; int size; @@ -31,18 +37,18 @@ struct Entry { }; // Hash a key -int hashFxn(int key) { +size_t hashFxn(int key) { std::hash hash; return hash(key); } // Performs linear probing to resolve collisions int linearProbe(int key, bool searching) { - int hash = static_cast(fabs(hashFxn(key))); + int hash = static_cast(hashFxn(key)); int i = 0; Entry entry; do { - int index = static_cast(fabs((hash + i) % totalSize)); + int index = static_cast((hash + i) % totalSize); entry = table[index]; if (searching) { if (entry.key == notPresent) { @@ -56,12 +62,14 @@ int linearProbe(int key, bool searching) { i++; } else { if (putProber(entry, key)) { - if (!rehashing) + if (!rehashing) { cout << "Spot found!" << endl; + } return index; } - if (!rehashing) + if (!rehashing) { cout << "Spot taken, looking at next" << endl; + } i++; } if (i == totalSize) { @@ -82,8 +90,9 @@ bool putProber(Entry entry, int key) { // Looks for a matching key bool searchingProber(Entry entry, int key) { - if (entry.key == key) + if (entry.key == key) { return true; + } return false; } @@ -108,27 +117,26 @@ void rehash() { // Necessary so wall of add info isn't printed all at once rehashing = true; int oldSize = totalSize; - Entry* oldTable = table; - // Really this should use the next prime number greater than totalSize * 2 - table = new Entry[totalSize * 2]; + std::vector oldTable(table); + // Really this should use the next prime number greater than totalSize * + // 2 totalSize *= 2; + table = std::vector(totalSize); for (int i = 0; i < oldSize; i++) { if (oldTable[i].key != -1 && oldTable[i].key != notPresent) { size--; // Size stays the same (add increments size) add(oldTable[i].key); } } - delete[] oldTable; + // delete[] oldTable; rehashing = false; cout << "Table was rehashed, new size is: " << totalSize << endl; } // Adds entry using linear probing. Checks for load factor here void add(int key) { - Entry* entry = new Entry(); - entry->key = key; int index = linearProbe(key, false); - table[index] = *entry; + table[index].key = key; // Load factor greater than 0.5 causes resizing if (++size / static_cast(totalSize) >= 0.5) { rehash(); @@ -152,7 +160,7 @@ void addInfo(int key) { display(); cout << endl; cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << fabs(hashFxn(key) % totalSize); + << " == " << hashFxn(key) % totalSize; cout << endl; add(key); cout << "New table: "; @@ -171,13 +179,14 @@ void removalInfo(int key) { cout << "New table: "; display(); } +} // namespace // I/O -int main(void) { - int cmd, hash, key; +int main() { + int cmd = 0, hash = 0, key = 0; cout << "Enter the initial size of Hash Table. = "; cin >> totalSize; - table = new Entry[totalSize]; + table = std::vector(totalSize); bool loop = true; while (loop) { system("pause"); @@ -191,37 +200,37 @@ int main(void) { cout << "6. Exit." << endl; cin >> cmd; switch (cmd) { - case 1: - cout << "Enter key to add = "; - cin >> key; - addInfo(key); - break; - case 2: - cout << "Enter key to remove = "; - cin >> key; - removalInfo(key); - break; - case 3: { - cout << "Enter key to search = "; - cin >> key; - Entry entry = table[linearProbe(key, true)]; - if (entry.key == notPresent) { - cout << "Key not present"; + case 1: + cout << "Enter key to add = "; + cin >> key; + addInfo(key); + break; + case 2: + cout << "Enter key to remove = "; + cin >> key; + removalInfo(key); + break; + case 3: { + cout << "Enter key to search = "; + cin >> key; + Entry entry = table[linearProbe(key, true)]; + if (entry.key == notPresent) { + cout << "Key not present"; + } + break; } - break; - } - case 4: - cout << "Enter element to generate hash = "; - cin >> key; - cout << "Hash of " << key << " is = " << fabs(hashFxn(key)); - break; - case 5: - display(); - break; - default: - loop = false; - break; - delete[] table; + case 4: + cout << "Enter element to generate hash = "; + cin >> key; + cout << "Hash of " << key << " is = " << hashFxn(key); + break; + case 5: + display(); + break; + default: + loop = false; + break; + // delete[] table; } cout << endl; } From 25efa07f2246be550e5f9692e86a517219071bf2 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 23 Jul 2020 18:28:53 -0400 Subject: [PATCH 09/21] fix quadratic_probing.... --- hashing/quadratic_probing_hash_table.cpp | 120 ++++++++++++----------- 1 file changed, 64 insertions(+), 56 deletions(-) diff --git a/hashing/quadratic_probing_hash_table.cpp b/hashing/quadratic_probing_hash_table.cpp index 971c2182d..1b9e2784a 100644 --- a/hashing/quadratic_probing_hash_table.cpp +++ b/hashing/quadratic_probing_hash_table.cpp @@ -1,25 +1,30 @@ -// Copyright 2019 - -#include +/** + * @file + * @author [achance6](https://github.com/achance6) + * @author [Krishna Vedala](https://github.com/kvedala) + * @brief + */ #include -#include #include #include +#include using std::cin; using std::cout; using std::endl; using std::string; +namespace { // keep the code local to this file by assigning them to an unnamed + // fwd declarations -struct Entry; +using Entry = struct Entry; bool putProber(Entry entry, int key); bool searchingProber(Entry entry, int key); void add(int key); // globals int notPresent; -struct Entry* table; +std::vector table; int totalSize; int tomb = -1; int size; @@ -32,19 +37,20 @@ struct Entry { }; // Hash a key -int hashFxn(int key) { +size_t hashFxn(int key) { std::hash hash; return hash(key); } // Performs quadratic probing to resolve collisions int quadraticProbe(int key, bool searching) { - int hash = static_cast(fabs(hashFxn(key))); + int hash = static_cast(hashFxn(key)); int i = 0; Entry entry; do { - int index = std::round(fabs( - (hash + static_cast(std::round(std::pow(i, 2)))) % totalSize)); + size_t index = + (hash + static_cast(std::round(std::pow(i, 2)))) % + totalSize; entry = table[index]; if (searching) { if (entry.key == notPresent) { @@ -58,15 +64,16 @@ int quadraticProbe(int key, bool searching) { i++; } else { if (putProber(entry, key)) { - if (!rehashing) + if (!rehashing) { cout << "Spot found!" << endl; + } return index; } if (!rehashing) { cout << "Spot taken, looking at next (next index = " - << std::round(fabs((hash + static_cast(std::round( - std::pow(i + 1, 2)))) % - totalSize)) + << (hash + + static_cast(std::round(std::pow(i + 1, 2)))) % + totalSize << endl; } i++; @@ -89,16 +96,18 @@ bool putProber(Entry entry, int key) { // Looks for a matching key bool searchingProber(Entry entry, int key) { - if (entry.key == key) + if (entry.key == key) { return true; + } return false; } // Helper Entry find(int key) { int index = quadraticProbe(key, true); - if (index == notPresent) + if (index == notPresent) { return Entry(); + } return table[index]; } @@ -123,27 +132,25 @@ void rehash() { // Necessary so wall of add info isn't printed all at once rehashing = true; int oldSize = totalSize; - Entry* oldTable = table; + std::vector oldTable(table); // Really this should use the next prime number greater than totalSize * 2 - table = new Entry[totalSize * 2]; totalSize *= 2; + table = std::vector(totalSize); for (int i = 0; i < oldSize; i++) { if (oldTable[i].key != -1 && oldTable[i].key != notPresent) { size--; // Size stays the same (add increments size) add(oldTable[i].key); } } - delete[] oldTable; + // delete[] oldTable; rehashing = false; cout << "Table was rehashed, new size is: " << totalSize << endl; } // Checks for load factor here void add(int key) { - Entry* entry = new Entry(); - entry->key = key; int index = quadraticProbe(key, false); - table[index] = *entry; + table[index].key = key; // Load factor greater than 0.5 causes resizing if (++size / static_cast(totalSize) >= 0.5) { rehash(); @@ -167,7 +174,7 @@ void addInfo(int key) { display(); cout << endl; cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << fabs(hashFxn(key) % totalSize); + << " == " << hashFxn(key) % totalSize; cout << endl; add(key); cout << "New table: "; @@ -186,13 +193,14 @@ void removalInfo(int key) { cout << "New table: "; display(); } +} // namespace // I/O -int main(void) { - int cmd, hash, key; +int main() { + int cmd = 0, hash = 0, key = 0; cout << "Enter the initial size of Hash Table. = "; cin >> totalSize; - table = new Entry[totalSize]; + table = std::vector(totalSize); bool loop = true; while (loop) { system("pause"); @@ -206,37 +214,37 @@ int main(void) { cout << "6. Exit." << endl; cin >> cmd; switch (cmd) { - case 1: - cout << "Enter key to add = "; - cin >> key; - addInfo(key); - break; - case 2: - cout << "Enter key to remove = "; - cin >> key; - removalInfo(key); - break; - case 3: { - cout << "Enter key to search = "; - cin >> key; - Entry entry = table[quadraticProbe(key, true)]; - if (entry.key == notPresent) { - cout << "Key not present"; + case 1: + cout << "Enter key to add = "; + cin >> key; + addInfo(key); + break; + case 2: + cout << "Enter key to remove = "; + cin >> key; + removalInfo(key); + break; + case 3: { + cout << "Enter key to search = "; + cin >> key; + Entry entry = table[quadraticProbe(key, true)]; + if (entry.key == notPresent) { + cout << "Key not present"; + } + break; } - break; - } - case 4: - cout << "Enter element to generate hash = "; - cin >> key; - cout << "Hash of " << key << " is = " << fabs(hashFxn(key)); - break; - case 5: - display(); - break; - default: - loop = false; - break; - delete[] table; + case 4: + cout << "Enter element to generate hash = "; + cin >> key; + cout << "Hash of " << key << " is = " << hashFxn(key); + break; + case 5: + display(); + break; + default: + loop = false; + break; + // delete[] table; } cout << endl; } From 61c5998a1646b7442ed0af73c52d178371d4417e Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sat, 25 Jul 2020 10:48:37 -0400 Subject: [PATCH 10/21] updated docs - double_hash_hash_table --- hashing/double_hash_hash_table.cpp | 185 +++++++++++++++++------------ 1 file changed, 111 insertions(+), 74 deletions(-) diff --git a/hashing/double_hash_hash_table.cpp b/hashing/double_hash_hash_table.cpp index 5a9615b35..f8c9872d6 100644 --- a/hashing/double_hash_hash_table.cpp +++ b/hashing/double_hash_hash_table.cpp @@ -2,18 +2,13 @@ * @file double_hash_hash_table.cpp * @author [achance6](https://github.com/achance6) * @author [Krishna Vedala](https://github.com/kvedala) - * @brief + * @brief Storage mechanism using double-hashed keys. + * @note The implementation can be optimized by using OOP style. */ #include #include -#include #include -using std::cin; -using std::cout; -using std::endl; -using std::string; - namespace { // keep the code local to this file by assigning them to an unnamed // namespace @@ -31,25 +26,42 @@ int tomb = -1; int size; bool rehashing; -// Node that holds key +/** Node object that holds key */ struct Entry { - explicit Entry(int key = notPresent) : key(key) {} - int key; + explicit Entry(int key = notPresent) : key(key) {} ///< constructor + int key; ///< key value }; -// Hash a key +/** + * @brief Hash a key. Uses the STL library's `std::hash()` function. + * + * @param key value to hash + * @return hash value of the key + */ size_t hashFxn(int key) { std::hash hash; return hash(key); } -// Used for second hash function +/** + * @brief Used for second hash function + * + * @param key key value to hash + * @return hash value of the key + */ size_t otherHashFxn(int key) { std::hash hash; return 1 + (7 - (hash(key) % 7)); } -// Performs double hashing to resolve collisions +/** + * @brief Performs double hashing to resolve collisions + * + * @param key key value to apply double-hash on + * @param searching `true` to check for conflicts + * @return Index of key when found + * @return new hash if no conflicts present + */ int doubleHash(int key, bool searching) { int hash = static_cast(hashFxn(key)); int i = 0; @@ -63,36 +75,42 @@ int doubleHash(int key, bool searching) { return notPresent; } if (searchingProber(entry, key)) { - cout << "Found key!" << endl; + std::cout << "Found key!" << std::endl; return index; } - cout << "Found tombstone or equal hash, checking next" << endl; + std::cout << "Found tombstone or equal hash, checking next" + << std::endl; i++; } else { if (putProber(entry, key)) { if (!rehashing) { - cout << "Spot found!" << endl; + std::cout << "Spot found!" << std::endl; } return index; } if (!rehashing) { - cout << "Spot taken, looking at next (next index:" - << " " - << static_cast(hash + (i * otherHashFxn(key))) % - totalSize - << ")" << endl; + std::cout << "Spot taken, looking at next (next index:" + << " " + << static_cast(hash + (i * otherHashFxn(key))) % + totalSize + << ")" << std::endl; } i++; } if (i == totalSize * 100) { - cout << "DoubleHash probe failed" << endl; + std::cout << "DoubleHash probe failed" << std::endl; return notPresent; } } while (entry.key != notPresent); return notPresent; } -// Finds empty spot +/** Finds empty spot in a vector + * @param entry vector to search in + * @param key key to search for + * @returns `true` if key is not present or is a `toumb` + * @returns `false` is already occupied + */ bool putProber(Entry entry, int key) { if (entry.key == notPresent || entry.key == tomb) { return true; @@ -100,7 +118,12 @@ bool putProber(Entry entry, int key) { return false; } -// Looks for a matching key +/** Looks for a matching key + * @param entry vector to search in + * @param key key value to search + * @returns `true` if found + * @returns `false` if not found + */ bool searchingProber(Entry entry, int key) { if (entry.key == key) { return true; @@ -108,23 +131,27 @@ bool searchingProber(Entry entry, int key) { return false; } -// Displays the table +/** Displays the table + * @returns None + */ void display() { for (int i = 0; i < totalSize; i++) { if (table[i].key == notPresent) { - cout << " Empty "; + std::cout << " Empty "; } else if (table[i].key == tomb) { - cout << " Tomb "; + std::cout << " Tomb "; } else { - cout << " "; - cout << table[i].key; - cout << " "; + std::cout << " "; + std::cout << table[i].key; + std::cout << " "; } } - cout << endl; + std::cout << std::endl; } -// Rehashes the table into a bigger table +/** Rehashes the table into a bigger table + * @returns None + */ void rehash() { // Necessary so wall of add info isn't printed all at once rehashing = true; @@ -143,10 +170,12 @@ void rehash() { // oldTable.reset(); rehashing = false; - cout << "Table was rehashed, new size is: " << totalSize << endl; + std::cout << "Table was rehashed, new size is: " << totalSize << std::endl; } -// Checks for load factor here +/** Checks for load factor here + * @param key key value to add to the table + */ void add(int key) { // auto* entry = new Entry(); // entry->key = key; @@ -158,86 +187,94 @@ void add(int key) { } } -// Removes key. Leaves tombstone upon removal. +/** Removes key. Leaves tombstone upon removal. + * @param key key value to remove + */ void remove(int key) { int index = doubleHash(key, true); if (index == notPresent) { - cout << "key not found" << endl; + std::cout << "key not found" << std::endl; } table[index].key = tomb; - cout << "Removal successful, leaving tombstone" << endl; + std::cout << "Removal successful, leaving tombstone" << std::endl; size--; } -// Information about the adding process +/** Information about the adding process + * @param key key value to add to table + */ void addInfo(int key) { - cout << "Initial table: "; + std::cout << "Initial table: "; display(); - cout << endl; - cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << hashFxn(key) % totalSize; - cout << endl; + std::cout << std::endl; + std::cout << "hash of " << key << " is " << hashFxn(key) << " % " + << totalSize << " == " << hashFxn(key) % totalSize; + std::cout << std::endl; add(key); - cout << "New table: "; + std::cout << "New table: "; display(); } -// Information about removal process +/** Information about removal process + * @param key key value to remove from table + */ void removalInfo(int key) { - cout << "Initial table: "; + std::cout << "Initial table: "; display(); - cout << endl; - cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << hashFxn(key) % totalSize; - cout << endl; + std::cout << std::endl; + std::cout << "hash of " << key << " is " << hashFxn(key) << " % " + << totalSize << " == " << hashFxn(key) % totalSize; + std::cout << std::endl; remove(key); - cout << "New table: "; + std::cout << "New table: "; display(); } } // namespace -// I/O +/** Main program + * @returns None + */ int main() { int cmd = 0, hash = 0, key = 0; - cout << "Enter the initial size of Hash Table. = "; - cin >> totalSize; + std::cout << "Enter the initial size of Hash Table. = "; + std::cin >> totalSize; table = std::vector(totalSize); bool loop = true; while (loop) { system("pause"); - cout << endl; - cout << "PLEASE CHOOSE -" << endl; - cout << "1. Add key. (Numeric only)" << endl; - cout << "2. Remove key." << endl; - cout << "3. Find key." << endl; - cout << "4. Generate Hash. (Numeric only)" << endl; - cout << "5. Display Hash table." << endl; - cout << "6. Exit." << endl; - cin >> cmd; + std::cout << std::endl; + std::cout << "PLEASE CHOOSE -" << std::endl; + std::cout << "1. Add key. (Numeric only)" << std::endl; + std::cout << "2. Remove key." << std::endl; + std::cout << "3. Find key." << std::endl; + std::cout << "4. Generate Hash. (Numeric only)" << std::endl; + std::cout << "5. Display Hash table." << std::endl; + std::cout << "6. Exit." << std::endl; + std::cin >> cmd; switch (cmd) { case 1: - cout << "Enter key to add = "; - cin >> key; + std::cout << "Enter key to add = "; + std::cin >> key; addInfo(key); break; case 2: - cout << "Enter key to remove = "; - cin >> key; + std::cout << "Enter key to remove = "; + std::cin >> key; removalInfo(key); break; case 3: { - cout << "Enter key to search = "; - cin >> key; + std::cout << "Enter key to search = "; + std::cin >> key; Entry entry = table[doubleHash(key, true)]; if (entry.key == notPresent) { - cout << "Key not present"; + std::cout << "Key not present"; } break; } case 4: - cout << "Enter element to generate hash = "; - cin >> key; - cout << "Hash of " << key << " is = " << hashFxn(key); + std::cout << "Enter element to generate hash = "; + std::cin >> key; + std::cout << "Hash of " << key << " is = " << hashFxn(key); break; case 5: display(); @@ -247,7 +284,7 @@ int main() { break; // delete[] table; } - cout << endl; + std::cout << std::endl; } return 0; } From c7dd883b9d07b113d52427a339c04df3837f4b45 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Wed, 29 Jul 2020 12:33:53 -0400 Subject: [PATCH 11/21] added wiki reference --- hashing/double_hash_hash_table.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hashing/double_hash_hash_table.cpp b/hashing/double_hash_hash_table.cpp index f8c9872d6..1a8c167d7 100644 --- a/hashing/double_hash_hash_table.cpp +++ b/hashing/double_hash_hash_table.cpp @@ -2,7 +2,8 @@ * @file double_hash_hash_table.cpp * @author [achance6](https://github.com/achance6) * @author [Krishna Vedala](https://github.com/kvedala) - * @brief Storage mechanism using double-hashed keys. + * @brief Storage mechanism using [double-hashed + * keys](https://en.wikipedia.org/wiki/Double_hashing). * @note The implementation can be optimized by using OOP style. */ #include @@ -18,7 +19,7 @@ bool putProber(Entry entry, int key); bool searchingProber(Entry entry, int key); void add(int key); -// globals +// Undocumented globals int notPresent; std::vector table; int totalSize; From 7d3adb00234f597e4404fd831f3b8d0e6f6ac6f1 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Wed, 29 Jul 2020 12:41:31 -0400 Subject: [PATCH 12/21] updated program docs --- hashing/linear_probing_hash_table.cpp | 75 +++++++++++++++++++-------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/hashing/linear_probing_hash_table.cpp b/hashing/linear_probing_hash_table.cpp index a125f016b..e807c546f 100644 --- a/hashing/linear_probing_hash_table.cpp +++ b/hashing/linear_probing_hash_table.cpp @@ -2,7 +2,9 @@ * @file * @author [achance6](https://github.com/achance6) * @author [Krishna Vedala](https://github.com/kvedala) - * @brief + * @brief Storage mechanism using [linear probing + * hash](https://en.wikipedia.org/wiki/Linear_probing) keys. + * @note The implementation can be optimized by using OOP style. */ #include #include @@ -16,13 +18,18 @@ using std::string; namespace { // keep the code local to this file by assigning them to an unnamed // namespace +/** Node object that holds key */ +struct Entry { + explicit Entry(int key = notPresent) : key(key) {} ///< constructor + int key; ///< key value +}; + // fwd declarations -using Entry = struct Entry; bool putProber(Entry entry, int key); bool searchingProber(Entry entry, int key); void add(int key); -// globals +// Undocumented globals int notPresent; std::vector table; int totalSize; @@ -30,19 +37,21 @@ int tomb = -1; int size; bool rehashing; -// Node that holds key -struct Entry { - explicit Entry(int key = notPresent) : key(key) {} - int key; -}; - -// Hash a key +/** + * @brief Hash a key. Uses the STL library's `std::hash()` function. + * + * @param key value to hash + * @return hash value of the key + */ size_t hashFxn(int key) { std::hash hash; return hash(key); } -// Performs linear probing to resolve collisions +/** Performs linear probing to resolve collisions + * @param key key value to hash + * @return hash value of the key + */ int linearProbe(int key, bool searching) { int hash = static_cast(hashFxn(key)); int i = 0; @@ -80,23 +89,33 @@ int linearProbe(int key, bool searching) { return notPresent; } -// Finds empty spot -bool putProber(Entry entry, int key) { +/** Finds empty spot + * @param entry instance to check in + * @param key key value to hash + * @return hash value of the key + */ +bool putProber(const Entry& entry, int key) { if (entry.key == notPresent || entry.key == tomb) { return true; } return false; } -// Looks for a matching key -bool searchingProber(Entry entry, int key) { +/** Looks for a matching key + * @param entry instance to check in + * @param key key value to hash + * @return hash value of the key + */ +bool searchingProber(const Entry& entry, int key) { if (entry.key == key) { return true; } return false; } -// Displays the table +/** Function to displays the table + * @returns none + */ void display() { for (int i = 0; i < totalSize; i++) { if (table[i].key == notPresent) { @@ -112,7 +131,9 @@ void display() { cout << endl; } -// Rehashes the table into a bigger table +/** Rehashes the table into a bigger table + * @returns None + */ void rehash() { // Necessary so wall of add info isn't printed all at once rehashing = true; @@ -133,7 +154,9 @@ void rehash() { cout << "Table was rehashed, new size is: " << totalSize << endl; } -// Adds entry using linear probing. Checks for load factor here +/** Adds entry using linear probing. Checks for load factor here + * @param key key value to hash and add + */ void add(int key) { int index = linearProbe(key, false); table[index].key = key; @@ -143,7 +166,9 @@ void add(int key) { } } -// Removes key. Leaves tombstone upon removal. +/** Removes key. Leaves tombstone upon removal. + * @param key key value to hash and remove + */ void remove(int key) { int index = linearProbe(key, true); if (index == notPresent) { @@ -154,7 +179,9 @@ void remove(int key) { size--; } -// Information about the adding process +/** Information about the adding process + * @param key key value to hash and add + */ void addInfo(int key) { cout << "Initial table: "; display(); @@ -167,7 +194,9 @@ void addInfo(int key) { display(); } -// Information about removal process +/** Information about removal process + * @param key key value to hash and remove + */ void removalInfo(int key) { cout << "Initial table: "; display(); @@ -181,7 +210,9 @@ void removalInfo(int key) { } } // namespace -// I/O +/** Main function + * @returns 0 on success + */ int main() { int cmd = 0, hash = 0, key = 0; cout << "Enter the initial size of Hash Table. = "; From 842c5fb25171356ed3c2fd87a4208ca58edd3baa Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Wed, 29 Jul 2020 12:46:29 -0400 Subject: [PATCH 13/21] fix forward declarations --- hashing/double_hash_hash_table.cpp | 8 ++++---- hashing/linear_probing_hash_table.cpp | 17 +++++++++-------- hashing/quadratic_probing_hash_table.cpp | 8 ++++---- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/hashing/double_hash_hash_table.cpp b/hashing/double_hash_hash_table.cpp index 1a8c167d7..ae872c4f8 100644 --- a/hashing/double_hash_hash_table.cpp +++ b/hashing/double_hash_hash_table.cpp @@ -15,8 +15,8 @@ namespace { // keep the code local to this file by assigning them to an unnamed // fwd declarations using Entry = struct Entry; -bool putProber(Entry entry, int key); -bool searchingProber(Entry entry, int key); +bool putProber(const Entry& entry, int key); +bool searchingProber(const Entry& entry, int key); void add(int key); // Undocumented globals @@ -112,7 +112,7 @@ int doubleHash(int key, bool searching) { * @returns `true` if key is not present or is a `toumb` * @returns `false` is already occupied */ -bool putProber(Entry entry, int key) { +bool putProber(const Entry& entry, int key) { if (entry.key == notPresent || entry.key == tomb) { return true; } @@ -125,7 +125,7 @@ bool putProber(Entry entry, int key) { * @returns `true` if found * @returns `false` if not found */ -bool searchingProber(Entry entry, int key) { +bool searchingProber(const Entry& entry, int key) { if (entry.key == key) { return true; } diff --git a/hashing/linear_probing_hash_table.cpp b/hashing/linear_probing_hash_table.cpp index e807c546f..47739e8a5 100644 --- a/hashing/linear_probing_hash_table.cpp +++ b/hashing/linear_probing_hash_table.cpp @@ -18,15 +18,10 @@ using std::string; namespace { // keep the code local to this file by assigning them to an unnamed // namespace -/** Node object that holds key */ -struct Entry { - explicit Entry(int key = notPresent) : key(key) {} ///< constructor - int key; ///< key value -}; - // fwd declarations -bool putProber(Entry entry, int key); -bool searchingProber(Entry entry, int key); +using Entry = struct Entry; +bool putProber(const Entry& entry, int key); +bool searchingProber(const Entry& entry, int key); void add(int key); // Undocumented globals @@ -37,6 +32,12 @@ int tomb = -1; int size; bool rehashing; +/** Node object that holds key */ +struct Entry { + explicit Entry(int key = notPresent) : key(key) {} ///< constructor + int key; ///< key value +}; + /** * @brief Hash a key. Uses the STL library's `std::hash()` function. * diff --git a/hashing/quadratic_probing_hash_table.cpp b/hashing/quadratic_probing_hash_table.cpp index 1b9e2784a..55dfd681b 100644 --- a/hashing/quadratic_probing_hash_table.cpp +++ b/hashing/quadratic_probing_hash_table.cpp @@ -18,8 +18,8 @@ namespace { // keep the code local to this file by assigning them to an unnamed // fwd declarations using Entry = struct Entry; -bool putProber(Entry entry, int key); -bool searchingProber(Entry entry, int key); +bool putProber(const Entry& entry, int key); +bool searchingProber(const Entry& entry, int key); void add(int key); // globals @@ -87,7 +87,7 @@ int quadraticProbe(int key, bool searching) { } // Finds empty spot -bool putProber(Entry entry, int key) { +bool putProber(const Entry& entry, int key) { if (entry.key == notPresent || entry.key == tomb) { return true; } @@ -95,7 +95,7 @@ bool putProber(Entry entry, int key) { } // Looks for a matching key -bool searchingProber(Entry entry, int key) { +bool searchingProber(const Entry& entry, int key) { if (entry.key == key) { return true; } From 1ffb1a38e76df2da25f588f9ae02e1243a9b5567 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Wed, 29 Jul 2020 12:48:32 -0400 Subject: [PATCH 14/21] fix docs --- hashing/quadratic_probing_hash_table.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hashing/quadratic_probing_hash_table.cpp b/hashing/quadratic_probing_hash_table.cpp index 55dfd681b..7af55914f 100644 --- a/hashing/quadratic_probing_hash_table.cpp +++ b/hashing/quadratic_probing_hash_table.cpp @@ -2,7 +2,9 @@ * @file * @author [achance6](https://github.com/achance6) * @author [Krishna Vedala](https://github.com/kvedala) - * @brief + * @brief Storage mechanism using [quadratic probing + * hash](https://en.wikipedia.org/wiki/Quadratic_probing) keys. + * @note The implementation can be optimized by using OOP style. */ #include #include From d89b2df2f0dc04e5f2ccce8f0011597dec8aa2bf Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Wed, 29 Jul 2020 13:24:37 -0400 Subject: [PATCH 15/21] replace using std::cin, etc --- hashing/linear_probing_hash_table.cpp | 103 ++++++++++----------- hashing/quadratic_probing_hash_table.cpp | 111 +++++++++++------------ 2 files changed, 102 insertions(+), 112 deletions(-) diff --git a/hashing/linear_probing_hash_table.cpp b/hashing/linear_probing_hash_table.cpp index 47739e8a5..45d37864d 100644 --- a/hashing/linear_probing_hash_table.cpp +++ b/hashing/linear_probing_hash_table.cpp @@ -7,14 +7,8 @@ * @note The implementation can be optimized by using OOP style. */ #include -#include #include -using std::cin; -using std::cout; -using std::endl; -using std::string; - namespace { // keep the code local to this file by assigning them to an unnamed // namespace @@ -65,25 +59,26 @@ int linearProbe(int key, bool searching) { return notPresent; } if (searchingProber(entry, key)) { - cout << "Found key!" << endl; + std::cout << "Found key!" << std::endl; return index; } - cout << "Found tombstone or equal hash, checking next" << endl; + std::cout << "Found tombstone or equal hash, checking next" + << std::endl; i++; } else { if (putProber(entry, key)) { if (!rehashing) { - cout << "Spot found!" << endl; + std::cout << "Spot found!" << std::endl; } return index; } if (!rehashing) { - cout << "Spot taken, looking at next" << endl; + std::cout << "Spot taken, looking at next" << std::endl; } i++; } if (i == totalSize) { - cout << "Linear probe failed" << endl; + std::cout << "Linear probe failed" << std::endl; return notPresent; } } while (entry.key != notPresent); @@ -120,16 +115,16 @@ bool searchingProber(const Entry& entry, int key) { void display() { for (int i = 0; i < totalSize; i++) { if (table[i].key == notPresent) { - cout << " Empty "; + std::cout << " Empty "; } else if (table[i].key == tomb) { - cout << " Tomb "; + std::cout << " Tomb "; } else { - cout << " "; - cout << table[i].key; - cout << " "; + std::cout << " "; + std::cout << table[i].key; + std::cout << " "; } } - cout << endl; + std::cout << std::endl; } /** Rehashes the table into a bigger table @@ -152,7 +147,7 @@ void rehash() { } // delete[] oldTable; rehashing = false; - cout << "Table was rehashed, new size is: " << totalSize << endl; + std::cout << "Table was rehashed, new size is: " << totalSize << std::endl; } /** Adds entry using linear probing. Checks for load factor here @@ -173,9 +168,9 @@ void add(int key) { void remove(int key) { int index = linearProbe(key, true); if (index == notPresent) { - cout << "key not found" << endl; + std::cout << "key not found" << std::endl; } - cout << "Removal Successful, leaving tomb" << endl; + std::cout << "Removal Successful, leaving tomb" << std::endl; table[index].key = tomb; size--; } @@ -184,14 +179,14 @@ void remove(int key) { * @param key key value to hash and add */ void addInfo(int key) { - cout << "Initial table: "; + std::cout << "Initial table: "; display(); - cout << endl; - cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << hashFxn(key) % totalSize; - cout << endl; + std::cout << std::endl; + std::cout << "hash of " << key << " is " << hashFxn(key) << " % " + << totalSize << " == " << hashFxn(key) % totalSize; + std::cout << std::endl; add(key); - cout << "New table: "; + std::cout << "New table: "; display(); } @@ -199,14 +194,14 @@ void addInfo(int key) { * @param key key value to hash and remove */ void removalInfo(int key) { - cout << "Initial table: "; + std::cout << "Initial table: "; display(); - cout << endl; - cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << hashFxn(key) % totalSize; - cout << endl; + std::cout << std::endl; + std::cout << "hash of " << key << " is " << hashFxn(key) << " % " + << totalSize << " == " << hashFxn(key) % totalSize; + std::cout << std::endl; remove(key); - cout << "New table: "; + std::cout << "New table: "; display(); } } // namespace @@ -216,45 +211,45 @@ void removalInfo(int key) { */ int main() { int cmd = 0, hash = 0, key = 0; - cout << "Enter the initial size of Hash Table. = "; - cin >> totalSize; + std::cout << "Enter the initial size of Hash Table. = "; + std::cin >> totalSize; table = std::vector(totalSize); bool loop = true; while (loop) { system("pause"); - cout << endl; - cout << "PLEASE CHOOSE -" << endl; - cout << "1. Add key. (Numeric only)" << endl; - cout << "2. Remove key." << endl; - cout << "3. Find key." << endl; - cout << "4. Generate Hash. (Numeric only)" << endl; - cout << "5. Display Hash table." << endl; - cout << "6. Exit." << endl; - cin >> cmd; + std::cout << std::endl; + std::cout << "PLEASE CHOOSE -" << std::endl; + std::cout << "1. Add key. (Numeric only)" << std::endl; + std::cout << "2. Remove key." << std::endl; + std::cout << "3. Find key." << std::endl; + std::cout << "4. Generate Hash. (Numeric only)" << std::endl; + std::cout << "5. Display Hash table." << std::endl; + std::cout << "6. Exit." << std::endl; + std::cin >> cmd; switch (cmd) { case 1: - cout << "Enter key to add = "; - cin >> key; + std::cout << "Enter key to add = "; + std::cin >> key; addInfo(key); break; case 2: - cout << "Enter key to remove = "; - cin >> key; + std::cout << "Enter key to remove = "; + std::cin >> key; removalInfo(key); break; case 3: { - cout << "Enter key to search = "; - cin >> key; + std::cout << "Enter key to search = "; + std::cin >> key; Entry entry = table[linearProbe(key, true)]; if (entry.key == notPresent) { - cout << "Key not present"; + std::cout << "Key not present"; } break; } case 4: - cout << "Enter element to generate hash = "; - cin >> key; - cout << "Hash of " << key << " is = " << hashFxn(key); + std::cout << "Enter element to generate hash = "; + std::cin >> key; + std::cout << "Hash of " << key << " is = " << hashFxn(key); break; case 5: display(); @@ -264,7 +259,7 @@ int main() { break; // delete[] table; } - cout << endl; + std::cout << std::endl; } return 0; } diff --git a/hashing/quadratic_probing_hash_table.cpp b/hashing/quadratic_probing_hash_table.cpp index 7af55914f..ac779eed5 100644 --- a/hashing/quadratic_probing_hash_table.cpp +++ b/hashing/quadratic_probing_hash_table.cpp @@ -8,14 +8,8 @@ */ #include #include -#include #include -using std::cin; -using std::cout; -using std::endl; -using std::string; - namespace { // keep the code local to this file by assigning them to an unnamed // fwd declarations @@ -59,29 +53,30 @@ int quadraticProbe(int key, bool searching) { return notPresent; } if (searchingProber(entry, key)) { - cout << "Found key!" << endl; + std::cout << "Found key!" << std::endl; return index; } - cout << "Found tombstone or equal hash, checking next" << endl; + std::cout << "Found tombstone or equal hash, checking next" + << std::endl; i++; } else { if (putProber(entry, key)) { if (!rehashing) { - cout << "Spot found!" << endl; + std::cout << "Spot found!" << std::endl; } return index; } if (!rehashing) { - cout << "Spot taken, looking at next (next index = " - << (hash + - static_cast(std::round(std::pow(i + 1, 2)))) % - totalSize - << endl; + std::cout << "Spot taken, looking at next (next index = " + << (hash + static_cast( + std::round(std::pow(i + 1, 2)))) % + totalSize + << std::endl; } i++; } if (i == totalSize * 100) { - cout << "Quadratic probe failed (infinite loop)" << endl; + std::cout << "Quadratic probe failed (infinite loop)" << std::endl; return notPresent; } } while (entry.key != notPresent); @@ -117,16 +112,16 @@ Entry find(int key) { void display() { for (int i = 0; i < totalSize; i++) { if (table[i].key == notPresent) { - cout << " Empty "; + std::cout << " Empty "; } else if (table[i].key == tomb) { - cout << " Tomb "; + std::cout << " Tomb "; } else { - cout << " "; - cout << table[i].key; - cout << " "; + std::cout << " "; + std::cout << table[i].key; + std::cout << " "; } } - cout << endl; + std::cout << std::endl; } // Rehashes the table into a bigger table @@ -146,7 +141,7 @@ void rehash() { } // delete[] oldTable; rehashing = false; - cout << "Table was rehashed, new size is: " << totalSize << endl; + std::cout << "Table was rehashed, new size is: " << totalSize << std::endl; } // Checks for load factor here @@ -163,36 +158,36 @@ void add(int key) { void remove(int key) { int index = quadraticProbe(key, true); if (index == notPresent) { - cout << "key not found" << endl; + std::cout << "key not found" << std::endl; } table[index].key = tomb; - cout << "Removal successful, leaving tombstone" << endl; + std::cout << "Removal successful, leaving tombstone" << std::endl; size--; } // Information about the adding process void addInfo(int key) { - cout << "Initial table: "; + std::cout << "Initial table: "; display(); - cout << endl; - cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << hashFxn(key) % totalSize; - cout << endl; + std::cout << std::endl; + std::cout << "hash of " << key << " is " << hashFxn(key) << " % " + << totalSize << " == " << hashFxn(key) % totalSize; + std::cout << std::endl; add(key); - cout << "New table: "; + std::cout << "New table: "; display(); } // Information about removal process void removalInfo(int key) { - cout << "Initial table: "; + std::cout << "Initial table: "; display(); - cout << endl; - cout << "hash of " << key << " is " << hashFxn(key) << " % " << totalSize - << " == " << hashFxn(key) % totalSize; - cout << endl; + std::cout << std::endl; + std::cout << "hash of " << key << " is " << hashFxn(key) << " % " + << totalSize << " == " << hashFxn(key) % totalSize; + std::cout << std::endl; remove(key); - cout << "New table: "; + std::cout << "New table: "; display(); } } // namespace @@ -200,45 +195,45 @@ void removalInfo(int key) { // I/O int main() { int cmd = 0, hash = 0, key = 0; - cout << "Enter the initial size of Hash Table. = "; - cin >> totalSize; + std::cout << "Enter the initial size of Hash Table. = "; + std::cin >> totalSize; table = std::vector(totalSize); bool loop = true; while (loop) { system("pause"); - cout << endl; - cout << "PLEASE CHOOSE -" << endl; - cout << "1. Add key. (Numeric only)" << endl; - cout << "2. Remove key." << endl; - cout << "3. Find key." << endl; - cout << "4. Generate Hash. (Numeric only)" << endl; - cout << "5. Display Hash table." << endl; - cout << "6. Exit." << endl; - cin >> cmd; + std::cout << std::endl; + std::cout << "PLEASE CHOOSE -" << std::endl; + std::cout << "1. Add key. (Numeric only)" << std::endl; + std::cout << "2. Remove key." << std::endl; + std::cout << "3. Find key." << std::endl; + std::cout << "4. Generate Hash. (Numeric only)" << std::endl; + std::cout << "5. Display Hash table." << std::endl; + std::cout << "6. Exit." << std::endl; + std::cin >> cmd; switch (cmd) { case 1: - cout << "Enter key to add = "; - cin >> key; + std::cout << "Enter key to add = "; + std::cin >> key; addInfo(key); break; case 2: - cout << "Enter key to remove = "; - cin >> key; + std::cout << "Enter key to remove = "; + std::cin >> key; removalInfo(key); break; case 3: { - cout << "Enter key to search = "; - cin >> key; + std::cout << "Enter key to search = "; + std::cin >> key; Entry entry = table[quadraticProbe(key, true)]; if (entry.key == notPresent) { - cout << "Key not present"; + std::cout << "Key not present"; } break; } case 4: - cout << "Enter element to generate hash = "; - cin >> key; - cout << "Hash of " << key << " is = " << hashFxn(key); + std::cout << "Enter element to generate hash = "; + std::cin >> key; + std::cout << "Hash of " << key << " is = " << hashFxn(key); break; case 5: display(); @@ -248,7 +243,7 @@ int main() { break; // delete[] table; } - cout << endl; + std::cout << std::endl; } return 0; } From e09637fb30884588a2b66f635c59cd8bbd76de3b Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Wed, 29 Jul 2020 19:22:05 -0400 Subject: [PATCH 16/21] named namespace --- hashing/quadratic_probing_hash_table.cpp | 101 +++++++++++++++++------ 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/hashing/quadratic_probing_hash_table.cpp b/hashing/quadratic_probing_hash_table.cpp index ac779eed5..5b7038637 100644 --- a/hashing/quadratic_probing_hash_table.cpp +++ b/hashing/quadratic_probing_hash_table.cpp @@ -10,8 +10,14 @@ #include #include -namespace { // keep the code local to this file by assigning them to an unnamed - +/** + * @addtogroup Open Addressing + * @{ + * @namespace quadratic_probing + * @brief An implementation of hash table using [quadratic + * probing](https://en.wikipedia.org/wiki/Quadratic_probing) algorithm. + */ +namespace quadratic_probing { // fwd declarations using Entry = struct Entry; bool putProber(const Entry& entry, int key); @@ -26,19 +32,27 @@ int tomb = -1; int size; bool rehashing; -// Node that holds key +/** Node that holds key + */ struct Entry { - explicit Entry(int key = notPresent) : key(key) {} - int key; + explicit Entry(int key = notPresent) : key(key) {} ///< constructor + int key; ///< key value }; -// Hash a key +/** Hash a key + * @param key key value to hash + * @returns hash of the key + */ size_t hashFxn(int key) { std::hash hash; return hash(key); } -// Performs quadratic probing to resolve collisions +/** Performs quadratic probing to resolve collisions + * @param key key value to search/probe + * @param searching `true` if only searching, `false1 if assigning + * @returns value of `notPresent`. + */ int quadraticProbe(int key, bool searching) { int hash = static_cast(hashFxn(key)); int i = 0; @@ -83,7 +97,12 @@ int quadraticProbe(int key, bool searching) { return notPresent; } -// Finds empty spot +/** Finds empty spot + * @param entry Instance of table entry + * @param key key value to search/probe + * @returns `true` if key is present + * @returns `false` if key is absent + */ bool putProber(const Entry& entry, int key) { if (entry.key == notPresent || entry.key == tomb) { return true; @@ -91,7 +110,12 @@ bool putProber(const Entry& entry, int key) { return false; } -// Looks for a matching key +/** Looks for a matching key + * @param entry Instance of table entry + * @param key key value to search/probe + * @returns `true` if key matches the entry + * @returns `false` if key does not match the entry + */ bool searchingProber(const Entry& entry, int key) { if (entry.key == key) { return true; @@ -99,7 +123,11 @@ bool searchingProber(const Entry& entry, int key) { return false; } -// Helper +/** Get the entry instance corresponding to a key + * @param key key value to search/probe + * @returns if present, the entry instance + * @returns if not present, a new instance + */ Entry find(int key) { int index = quadraticProbe(key, true); if (index == notPresent) { @@ -108,7 +136,9 @@ Entry find(int key) { return table[index]; } -// Displays the table +/** Displays the table + * @returns None + */ void display() { for (int i = 0; i < totalSize; i++) { if (table[i].key == notPresent) { @@ -124,7 +154,9 @@ void display() { std::cout << std::endl; } -// Rehashes the table into a bigger table +/** Rehashes the table into a bigger table + * @returns none + */ void rehash() { // Necessary so wall of add info isn't printed all at once rehashing = true; @@ -144,7 +176,9 @@ void rehash() { std::cout << "Table was rehashed, new size is: " << totalSize << std::endl; } -// Checks for load factor here +/** Checks for load factor here + * @param key key value to hash and add to table + */ void add(int key) { int index = quadraticProbe(key, false); table[index].key = key; @@ -154,7 +188,9 @@ void add(int key) { } } -// Removes key. Leaves tombstone upon removal. +/** Removes key. Leaves tombstone upon removal. + * @param key key value to hash and remove from table + */ void remove(int key) { int index = quadraticProbe(key, true); if (index == notPresent) { @@ -165,7 +201,9 @@ void remove(int key) { size--; } -// Information about the adding process +/** Information about the adding process + * @param key key value to hash and add to table + */ void addInfo(int key) { std::cout << "Initial table: "; display(); @@ -178,7 +216,9 @@ void addInfo(int key) { display(); } -// Information about removal process +/** Information about removal process + * @param key key value to hash and remove from table + */ void removalInfo(int key) { std::cout << "Initial table: "; display(); @@ -190,9 +230,19 @@ void removalInfo(int key) { std::cout << "New table: "; display(); } -} // namespace -// I/O +} // namespace quadratic_probing +/** + * @} + */ + +using quadratic_probing::Entry; +using quadratic_probing::table; +using quadratic_probing::totalSize; + +/** Main function + * @returns None + */ int main() { int cmd = 0, hash = 0, key = 0; std::cout << "Enter the initial size of Hash Table. = "; @@ -214,18 +264,20 @@ int main() { case 1: std::cout << "Enter key to add = "; std::cin >> key; - addInfo(key); + quadratic_probing::addInfo(key); break; case 2: std::cout << "Enter key to remove = "; std::cin >> key; - removalInfo(key); + quadratic_probing::removalInfo(key); break; case 3: { std::cout << "Enter key to search = "; std::cin >> key; - Entry entry = table[quadraticProbe(key, true)]; - if (entry.key == notPresent) { + quadratic_probing::Entry entry = + quadratic_probing::table[quadratic_probing::quadraticProbe( + key, true)]; + if (entry.key == quadratic_probing::notPresent) { std::cout << "Key not present"; } break; @@ -233,10 +285,11 @@ int main() { case 4: std::cout << "Enter element to generate hash = "; std::cin >> key; - std::cout << "Hash of " << key << " is = " << hashFxn(key); + std::cout << "Hash of " << key + << " is = " << quadratic_probing::hashFxn(key); break; case 5: - display(); + quadratic_probing::display(); break; default: loop = false; From a8b2825403c1ba3a1fc4c8d12d71091b24660a4e Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Wed, 29 Jul 2020 19:30:52 -0400 Subject: [PATCH 17/21] use named namespace --- hashing/linear_probing_hash_table.cpp | 33 ++++++++++++++++-------- hashing/quadratic_probing_hash_table.cpp | 3 ++- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/hashing/linear_probing_hash_table.cpp b/hashing/linear_probing_hash_table.cpp index 45d37864d..abde39783 100644 --- a/hashing/linear_probing_hash_table.cpp +++ b/hashing/linear_probing_hash_table.cpp @@ -9,9 +9,14 @@ #include #include -namespace { // keep the code local to this file by assigning them to an unnamed - // namespace - +/** + * @addtogroup Open Addressing + * @{ + * @namespace linear_probing + * @brief An implementation of hash table using [linear + * probing](https://en.wikipedia.org/wiki/Linear_probing) algorithm. + */ +namespace linear_probing { // fwd declarations using Entry = struct Entry; bool putProber(const Entry& entry, int key); @@ -204,7 +209,11 @@ void removalInfo(int key) { std::cout << "New table: "; display(); } -} // namespace +} // namespace linear_probing + +using linear_probing::Entry; +using linear_probing::table; +using linear_probing::totalSize; /** Main function * @returns 0 on success @@ -216,7 +225,8 @@ int main() { table = std::vector(totalSize); bool loop = true; while (loop) { - system("pause"); + std::cout << "\nPress a key to continue...\n"; + std::cin.get(); std::cout << std::endl; std::cout << "PLEASE CHOOSE -" << std::endl; std::cout << "1. Add key. (Numeric only)" << std::endl; @@ -230,18 +240,18 @@ int main() { case 1: std::cout << "Enter key to add = "; std::cin >> key; - addInfo(key); + linear_probing::addInfo(key); break; case 2: std::cout << "Enter key to remove = "; std::cin >> key; - removalInfo(key); + linear_probing::removalInfo(key); break; case 3: { std::cout << "Enter key to search = "; std::cin >> key; - Entry entry = table[linearProbe(key, true)]; - if (entry.key == notPresent) { + Entry entry = table[linear_probing::linearProbe(key, true)]; + if (entry.key == linear_probing::notPresent) { std::cout << "Key not present"; } break; @@ -249,10 +259,11 @@ int main() { case 4: std::cout << "Enter element to generate hash = "; std::cin >> key; - std::cout << "Hash of " << key << " is = " << hashFxn(key); + std::cout << "Hash of " << key + << " is = " << linear_probing::hashFxn(key); break; case 5: - display(); + linear_probing::display(); break; default: loop = false; diff --git a/hashing/quadratic_probing_hash_table.cpp b/hashing/quadratic_probing_hash_table.cpp index 5b7038637..d2071c288 100644 --- a/hashing/quadratic_probing_hash_table.cpp +++ b/hashing/quadratic_probing_hash_table.cpp @@ -250,7 +250,8 @@ int main() { table = std::vector(totalSize); bool loop = true; while (loop) { - system("pause"); + std::cout << "\nPress a key to continue...\n"; + std::cin.get(); std::cout << std::endl; std::cout << "PLEASE CHOOSE -" << std::endl; std::cout << "1. Add key. (Numeric only)" << std::endl; From b3cd53b26caf67714d3f5c8506e213df91532fbe Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Wed, 29 Jul 2020 19:35:29 -0400 Subject: [PATCH 18/21] added missing close paranthesis for addtogroup --- hashing/linear_probing_hash_table.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hashing/linear_probing_hash_table.cpp b/hashing/linear_probing_hash_table.cpp index abde39783..c5861522f 100644 --- a/hashing/linear_probing_hash_table.cpp +++ b/hashing/linear_probing_hash_table.cpp @@ -210,6 +210,9 @@ void removalInfo(int key) { display(); } } // namespace linear_probing +/** + * @} + */ using linear_probing::Entry; using linear_probing::table; From 9c5f8537527fadff95f30b0a52cecfb6f0a7228c Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Wed, 29 Jul 2020 19:43:33 -0400 Subject: [PATCH 19/21] remove pauses --- hashing/double_hash_hash_table.cpp | 36 ++++++++++++++++-------- hashing/linear_probing_hash_table.cpp | 4 +-- hashing/quadratic_probing_hash_table.cpp | 4 +-- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/hashing/double_hash_hash_table.cpp b/hashing/double_hash_hash_table.cpp index ae872c4f8..f5d803ba2 100644 --- a/hashing/double_hash_hash_table.cpp +++ b/hashing/double_hash_hash_table.cpp @@ -10,9 +10,14 @@ #include #include -namespace { // keep the code local to this file by assigning them to an unnamed - // namespace - +/** + * @addtogroup open_addressing Open Addressing + * @{ + * @namespace double_hashing + * @brief An implementation of hash table using [double + * hashing](https://en.wikipedia.org/wiki/Double_hashing) algorithm. + */ +namespace double_hashing { // fwd declarations using Entry = struct Entry; bool putProber(const Entry& entry, int key); @@ -230,10 +235,17 @@ void removalInfo(int key) { std::cout << "New table: "; display(); } -} // namespace +} // namespace double_hashing +/** + * @} + */ + +using double_hashing::Entry; +using double_hashing::table; +using double_hashing::totalSize; /** Main program - * @returns None + * @returns 0 on success */ int main() { int cmd = 0, hash = 0, key = 0; @@ -242,7 +254,6 @@ int main() { table = std::vector(totalSize); bool loop = true; while (loop) { - system("pause"); std::cout << std::endl; std::cout << "PLEASE CHOOSE -" << std::endl; std::cout << "1. Add key. (Numeric only)" << std::endl; @@ -256,18 +267,18 @@ int main() { case 1: std::cout << "Enter key to add = "; std::cin >> key; - addInfo(key); + double_hashing::addInfo(key); break; case 2: std::cout << "Enter key to remove = "; std::cin >> key; - removalInfo(key); + double_hashing::removalInfo(key); break; case 3: { std::cout << "Enter key to search = "; std::cin >> key; - Entry entry = table[doubleHash(key, true)]; - if (entry.key == notPresent) { + Entry entry = table[double_hashing::doubleHash(key, true)]; + if (entry.key == double_hashing::notPresent) { std::cout << "Key not present"; } break; @@ -275,10 +286,11 @@ int main() { case 4: std::cout << "Enter element to generate hash = "; std::cin >> key; - std::cout << "Hash of " << key << " is = " << hashFxn(key); + std::cout << "Hash of " << key + << " is = " << double_hashing::hashFxn(key); break; case 5: - display(); + double_hashing::display(); break; default: loop = false; diff --git a/hashing/linear_probing_hash_table.cpp b/hashing/linear_probing_hash_table.cpp index c5861522f..d87cb9cf7 100644 --- a/hashing/linear_probing_hash_table.cpp +++ b/hashing/linear_probing_hash_table.cpp @@ -10,7 +10,7 @@ #include /** - * @addtogroup Open Addressing + * @addtogroup open_addressing Open Addressing * @{ * @namespace linear_probing * @brief An implementation of hash table using [linear @@ -228,8 +228,6 @@ int main() { table = std::vector(totalSize); bool loop = true; while (loop) { - std::cout << "\nPress a key to continue...\n"; - std::cin.get(); std::cout << std::endl; std::cout << "PLEASE CHOOSE -" << std::endl; std::cout << "1. Add key. (Numeric only)" << std::endl; diff --git a/hashing/quadratic_probing_hash_table.cpp b/hashing/quadratic_probing_hash_table.cpp index d2071c288..258c009d0 100644 --- a/hashing/quadratic_probing_hash_table.cpp +++ b/hashing/quadratic_probing_hash_table.cpp @@ -11,7 +11,7 @@ #include /** - * @addtogroup Open Addressing + * @addtogroup open_addressing Open Addressing * @{ * @namespace quadratic_probing * @brief An implementation of hash table using [quadratic @@ -250,8 +250,6 @@ int main() { table = std::vector(totalSize); bool loop = true; while (loop) { - std::cout << "\nPress a key to continue...\n"; - std::cin.get(); std::cout << std::endl; std::cout << "PLEASE CHOOSE -" << std::endl; std::cout << "1. Add key. (Numeric only)" << std::endl; From 24cd164dd75c38b46037bb9b4b1f44e24b42cb4b Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 30 Jul 2020 18:30:02 -0400 Subject: [PATCH 20/21] better code structure --- hashing/chaining.cpp | 73 +++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/hashing/chaining.cpp b/hashing/chaining.cpp index 974b10584..7f0216886 100644 --- a/hashing/chaining.cpp +++ b/hashing/chaining.cpp @@ -2,29 +2,27 @@ * @file chaining.cpp * @author [vasutomar](https://github.com/vasutomar) * @author [Krishna Vedala](https://github.com/kvedala) - * @brief Implementation of node chains accessed using keys. + * @brief Implementation of [hash + * chains](https://en.wikipedia.org/wiki/Hash_chain). */ #include #include #include #include -namespace { // keep the code local to this file by assigning them to an unnamed - // namespace -/** - * @{ - * @brief Define a linked node - */ -struct Node { - int data{}; ///< data stored in the node - std::shared_ptr next; ///< pointer to the next node -}; - /** * @brief Chain class with a given modulus */ -class chain { +class hash_chain { private: + /** + * @brief Define a linked node + */ + using Node = struct Node { + int data{}; ///< data stored in the node + std::shared_ptr next; ///< pointer to the next node + }; + std::vector> head; ///< array of nodes int _mod; ///< modulus of the class @@ -34,7 +32,7 @@ class chain { * * @param mod modulus of the chain */ - explicit chain(int mod) : _mod(mod) { + explicit hash_chain(int mod) : _mod(mod) { while (mod--) head.push_back(nullptr); } @@ -46,7 +44,7 @@ class chain { */ void add(int x, int h) { std::shared_ptr curr; - std::shared_ptr temp(new struct Node); + std::shared_ptr temp(new Node); temp->data = x; temp->next = nullptr; if (!head[h]) { @@ -86,30 +84,49 @@ class chain { * * @param x value to compute modulus of * @return modulus of `x` + * @note declared as a + * [`virtual`](https://en.cppreference.com/w/cpp/language/virtual) so that + * custom implementations of the class can modify the hash function. */ - int hash(int x) const { return x % _mod; } + virtual int hash(int x) const { return x % _mod; } - void find(int x, int h) { - auto temp = head[h]; + /** + * @brief Find if a value and corresponding hash exist + * + * @param x value to search for + * @param h corresponding hash key + * @returns `true` if element found + * @returns `false` if element not found + */ + bool find(int x, int h) const { + std::shared_ptr temp = head[h]; if (!head[h]) { + // index does not exist! std::cout << "Element not found"; - return; + return false; } + + // scan for data value while (temp->data != x && temp->next) temp = temp->next; + if (temp->next) { std::cout << "Element found"; - } else { - if (temp->data == x) { - std::cout << "Element found"; - } else { - std::cout << "Element not found"; - } + return true; } + + // implicit else condition + // i.e., temp->next == nullptr + if (temp->data == x) { + std::cout << "Element found"; + return true; + } + + // further implicit else condition + std::cout << "Element not found"; + return false; } }; -} // namespace - /** Main function * @returns `0` always */ @@ -118,7 +135,7 @@ int main() { std::cout << "Enter the size of Hash Table. = "; std::cin >> mod; - chain mychain(mod); + hash_chain mychain(mod); bool loop = true; while (loop) { From 36298fd41b9007cf259fea51cbc64c54f9321104 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Thu, 30 Jul 2020 18:39:24 -0400 Subject: [PATCH 21/21] fix error reusing struct keyword --- hashing/chaining.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hashing/chaining.cpp b/hashing/chaining.cpp index 7f0216886..ae902c90e 100644 --- a/hashing/chaining.cpp +++ b/hashing/chaining.cpp @@ -23,7 +23,7 @@ class hash_chain { std::shared_ptr next; ///< pointer to the next node }; - std::vector> head; ///< array of nodes + std::vector> head; ///< array of nodes int _mod; ///< modulus of the class public: @@ -43,8 +43,8 @@ class hash_chain { * @param h height of the node */ void add(int x, int h) { - std::shared_ptr curr; - std::shared_ptr temp(new Node); + std::shared_ptr curr; + std::shared_ptr temp(new Node); temp->data = x; temp->next = nullptr; if (!head[h]) { @@ -61,7 +61,7 @@ class hash_chain { * @brief Display the chain */ void display() { - std::shared_ptr temp = nullptr; + std::shared_ptr temp = nullptr; int i = 0; for (i = 0; i < _mod; i++) { if (!head[i]) { @@ -99,7 +99,7 @@ class hash_chain { * @returns `false` if element not found */ bool find(int x, int h) const { - std::shared_ptr temp = head[h]; + std::shared_ptr temp = head[h]; if (!head[h]) { // index does not exist! std::cout << "Element not found"; @@ -182,4 +182,4 @@ int main() { display(&head1); display(&head2);*/ return 0; -} \ No newline at end of file +}