Week 14: Assignment - Hash Collisions
This commit is contained in:
parent
e153ae97f2
commit
114813c691
6
week-14/CMakeLists.txt
Normal file
6
week-14/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(week-14)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
add_executable(week-14 main.cpp)
|
312
week-14/main.cpp
Normal file
312
week-14/main.cpp
Normal file
@ -0,0 +1,312 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Champlain College SDEV-345-81
|
||||
*
|
||||
* C++ Week 14 Quadratic Probing, Hash Tables - (2020/12/13)
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Modify last week's program to demonstrate quadratic hash probing when a collision occurs.
|
||||
*
|
||||
* LAST WEEK
|
||||
* Write a menu driven program that creates a hash table using an array.
|
||||
* The program should give the user the following options and should run in an infinite loop:
|
||||
* 1) Insert key
|
||||
* 2) Delete key
|
||||
* 3) Display hash table
|
||||
* 4) Find key
|
||||
* The key should be a string and the program should calculate the location using a hash function.
|
||||
* The program should also prompt the user when there is a collision and when the hash table is full.
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Written by Llewellyn van der Merwe <llewellyn.vandermerw@mymail.champlain.edu>, December 2020
|
||||
* Copyright (C) 2020. All Rights Reserved
|
||||
* License GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class HashTable {
|
||||
private:
|
||||
// never use this as a value ;)
|
||||
const string emptyString = "|//_-++-_0.^.0_-++-_\\|";
|
||||
// the size of the array
|
||||
static const int tableSize = 8;
|
||||
// the inserted number
|
||||
int inserted = 0;
|
||||
// the HashBucket table array of nodes
|
||||
string HashBucket[tableSize];
|
||||
// found & empty key
|
||||
static const int emptyFoundKey = tableSize + 10;
|
||||
// found ;)
|
||||
int foundKey = emptyFoundKey;
|
||||
// empty ;)
|
||||
int emptyKey = emptyFoundKey;
|
||||
|
||||
// search for value in table
|
||||
bool find(string &value) {
|
||||
// get the HashBucket value of the string
|
||||
int key = Hash(value);
|
||||
// check if the value is found
|
||||
if (HashBucket[key] == value) {
|
||||
// if found set key
|
||||
foundKey = key;
|
||||
// found
|
||||
return true;
|
||||
}
|
||||
// continue the search
|
||||
return find(key, value);
|
||||
}
|
||||
|
||||
// smart search by key and value
|
||||
bool find(int &key, string &value) {
|
||||
// always reset the found
|
||||
emptyKey = emptyFoundKey;
|
||||
foundKey = emptyFoundKey;
|
||||
// use quadratic probing
|
||||
for (int pos = 0; pos < tableSize; pos++) {
|
||||
// Computing the new hash value
|
||||
key = Quadratic(key, pos);
|
||||
// check if the value is found
|
||||
if (HashBucket[key] == value) {
|
||||
// if found set key
|
||||
foundKey = key;
|
||||
// we found the value
|
||||
return true;
|
||||
} else if (HashBucket[key] == emptyString && emptyKey == emptyFoundKey) {
|
||||
// if first not found set key
|
||||
emptyKey = key;
|
||||
// but lets continue the search since on removal
|
||||
// we do not move the values to spaces
|
||||
// up to fill the array from the first hash
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hash function
|
||||
int Hash(string key) {
|
||||
int hash = 0;
|
||||
int tmp = key.length();
|
||||
// now loop the string value-key to get HashBucket
|
||||
for (int i = 0; i < tmp; i++) {
|
||||
hash = hash + (int) key[i];
|
||||
}
|
||||
// return the remainder
|
||||
return hash % tableSize;
|
||||
}
|
||||
|
||||
// quadratic insert function
|
||||
bool insert(int &key, string &value) {
|
||||
// check if key was found
|
||||
if (key != emptyFoundKey && HashBucket[key] == emptyString) {
|
||||
// since we have the key
|
||||
// we need to do the search
|
||||
// again
|
||||
HashBucket[key] = value;
|
||||
// count values inserted
|
||||
inserted++;
|
||||
// always reset just incase
|
||||
emptyKey = emptyFoundKey;
|
||||
return true;
|
||||
}
|
||||
// get the HashBucket value of the string
|
||||
key = Hash(value);
|
||||
// use quadratic probing
|
||||
for (int pos = 0; pos < tableSize; pos++) {
|
||||
// Computing the new hash value
|
||||
key = Quadratic(key, pos);
|
||||
if (HashBucket[key] == emptyString) {
|
||||
// Break the loop after
|
||||
// inserting the value
|
||||
// in the table
|
||||
HashBucket[key] = value;
|
||||
// count values inserted
|
||||
inserted++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// quadratic function
|
||||
int Quadratic(int key, int pos) {
|
||||
// Computing the new hash value
|
||||
int hash = key + pos * pos;
|
||||
// return the remainder
|
||||
return hash % tableSize;
|
||||
}
|
||||
|
||||
public:
|
||||
// our constructor of our HashBucket table
|
||||
HashTable() {
|
||||
// initialize the empty HashBucket tables
|
||||
for (int i = 0; i < tableSize; i++) {
|
||||
HashBucket[i] = emptyString;
|
||||
}
|
||||
}
|
||||
|
||||
// check if table is full
|
||||
bool isFull() {
|
||||
return inserted == tableSize;
|
||||
}
|
||||
|
||||
// add a node value
|
||||
void insert(string value) {
|
||||
// get the HashBucket value of the string
|
||||
int key = Hash(value);
|
||||
// check if the HashBucket has a collision
|
||||
if (HashBucket[key] == emptyString) {
|
||||
// give success adding info
|
||||
cout << "█ [Info] " << value << " - added successfully." << endl;
|
||||
// new value
|
||||
HashBucket[key] = value;
|
||||
// count values inserted
|
||||
inserted++;
|
||||
}
|
||||
// check if the value exist
|
||||
else if (!find(value)) {
|
||||
// prom the user if we should add to table
|
||||
cout << "█ [Warning] Collision detected." << endl;
|
||||
cout << "█ Do you still want to add: " << value << endl;
|
||||
cout << "█ Enter initial [yes/no]: ";
|
||||
char choice;
|
||||
cin >> choice;
|
||||
if ((choice == 'y' || choice == 'Y') && insert(emptyKey, value)) {
|
||||
// give collision info
|
||||
cout << "██████████████████████████████████████████████████████████" << endl;
|
||||
cout << "█ Collision resolved!" << endl;
|
||||
cout << "█ [Info] " << value << " - quadratic probing used." << endl;
|
||||
} else if (choice == 'y' || choice == 'Y') {
|
||||
// give error of quadratic probing failure
|
||||
cout << "██████████████████████████████████████████████████████████" << endl;
|
||||
cout << "█ [Error] " << value << " - not added." << endl;
|
||||
cout << "█ [Error] " << " - Quadratic probing failed." << endl;
|
||||
cout << "█ [Error] " << " - The array needs to be enlarged." << endl;
|
||||
} else {
|
||||
// give notice
|
||||
cout << "█ [Notice] " << value << " - not added." << endl;
|
||||
}
|
||||
} else {
|
||||
// give exists error
|
||||
cout << "█ [Error] " << value << " - exists." << endl;
|
||||
}
|
||||
cout << "██████████████████████████████████████████████████████████" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// search if the value is in the hash table
|
||||
void search(string &value) {
|
||||
// use the find method/function
|
||||
if (find(value)) {
|
||||
cout << "█ [Success] (" << foundKey << ") => " << value << " - found" << endl;
|
||||
} else {
|
||||
cout << "█ [Notice] " << value << " - not found" << endl;
|
||||
}
|
||||
cout << "██████████████████████████████████████████████████████████" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// display the hash table
|
||||
void display() {
|
||||
cout << "███ THE HASH TABLE ███████████████████████████████████████" << endl;
|
||||
cout << "██████████████████████████████████████████████████████████" << endl;
|
||||
for (int i = 0; i < tableSize; i++) {
|
||||
// only print out if bucket has values
|
||||
if (HashBucket[i] != emptyString) {
|
||||
cout << "█ (" << i << ") => ";
|
||||
cout << HashBucket[i] << endl;
|
||||
cout << "██████████████████████████████████████████████████████████" << endl;
|
||||
} else {
|
||||
// empty notice
|
||||
cout << "█ (" << i << ") =-" << endl;
|
||||
cout << "██████████████████████████████████████████████████████████" << endl;
|
||||
}
|
||||
}
|
||||
if (isFull()) {
|
||||
cout << "███ TABLE IS FULL ████████████████████████████████████████" << endl;
|
||||
} else {
|
||||
cout << "███ TABLE NOT FULL ███████████████████████████████████████" << endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// delete a value from the table
|
||||
void remove(string value) {
|
||||
// value found so remove
|
||||
if (find(value)) {
|
||||
// move the next node up
|
||||
HashBucket[foundKey] = emptyString;
|
||||
// count value removed
|
||||
inserted--;
|
||||
// removed notice
|
||||
cout << "█ [Success] " << value << " - removed." << endl;
|
||||
} else {
|
||||
// not found notice
|
||||
cout << "█ [Notice] " << value << " - not found." << endl;
|
||||
}
|
||||
cout << "██████████████████████████████████████████████████████████" << endl;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
// instantiate the table
|
||||
HashTable Table;
|
||||
// program loop (taken and adapted from this weeks module)
|
||||
char choice = 'b';
|
||||
string aKey;
|
||||
// start the program
|
||||
cout << "██████████████████████████████████████████████████████████" << endl;
|
||||
// interact with user
|
||||
while (choice != 'x') {
|
||||
// check if the table is full
|
||||
if (Table.isFull()) {
|
||||
cout << "█ Enter first letter of "
|
||||
<< "show, delete, or find: ";
|
||||
} else {
|
||||
cout << "█ Enter first letter of "
|
||||
<< "show, insert, delete, or find: ";
|
||||
}
|
||||
char choice;
|
||||
cin >> choice;
|
||||
// clear cin stream
|
||||
cin.clear();
|
||||
cin.ignore(numeric_limits<streamsize>::max(), '\n');
|
||||
switch (choice) {
|
||||
case 's':
|
||||
Table.display();
|
||||
break;
|
||||
case 'i':
|
||||
if (Table.isFull()) {
|
||||
cout << "█ Table is full" << endl;
|
||||
} else {
|
||||
cout << "█ Enter key value to insert: ";
|
||||
getline(cin, aKey);
|
||||
// now insert the string
|
||||
Table.insert(aKey);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
cout << "█ Enter key value to delete: ";
|
||||
getline(cin, aKey);
|
||||
// now remove the string
|
||||
Table.remove(aKey);
|
||||
break;
|
||||
case 'f':
|
||||
cout << "█ Enter key value to find: ";
|
||||
getline(cin, aKey);
|
||||
// now search for the string
|
||||
Table.search(aKey);
|
||||
break;
|
||||
default:
|
||||
cout << "█ Invalid entry" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user