-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e5dcd94
Showing
4 changed files
with
369 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# Created by .ignore support plugin (hsz.mobi) | ||
### Example user template template | ||
### Example user template | ||
|
||
# IntelliJ project files | ||
.idea | ||
*.iml | ||
out | ||
gen### macOS template | ||
# General | ||
.DS_Store | ||
.AppleDouble | ||
.LSOverride | ||
|
||
# Icon must end with two \r | ||
Icon | ||
|
||
# Thumbnails | ||
._* | ||
|
||
# Files that might appear in the root of a volume | ||
.DocumentRevisions-V100 | ||
.fseventsd | ||
.Spotlight-V100 | ||
.TemporaryItems | ||
.Trashes | ||
.VolumeIcon.icns | ||
.com.apple.timemachine.donotpresent | ||
|
||
# Directories potentially created on remote AFP share | ||
.AppleDB | ||
.AppleDesktop | ||
Network Trash Folder | ||
Temporary Items | ||
.apdisk | ||
### JetBrains template | ||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm | ||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 | ||
|
||
# User-specific stuff: | ||
.idea/**/workspace.xml | ||
.idea/**/tasks.xml | ||
.idea/dictionaries | ||
|
||
# Sensitive or high-churn files: | ||
.idea/**/dataSources/ | ||
.idea/**/dataSources.ids | ||
.idea/**/dataSources.xml | ||
.idea/**/dataSources.local.xml | ||
.idea/**/sqlDataSources.xml | ||
.idea/**/dynamic.xml | ||
.idea/**/uiDesigner.xml | ||
|
||
# Gradle: | ||
.idea/**/gradle.xml | ||
.idea/**/libraries | ||
|
||
# CMake | ||
cmake-build-debug/ | ||
|
||
# Mongo Explorer plugin: | ||
.idea/**/mongoSettings.xml | ||
|
||
## File-based project format: | ||
*.iws | ||
|
||
## Plugin-specific files: | ||
|
||
# IntelliJ | ||
out/ | ||
|
||
# mpeltonen/sbt-idea plugin | ||
.idea_modules/ | ||
|
||
# JIRA plugin | ||
atlassian-ide-plugin.xml | ||
|
||
# Cursive Clojure plugin | ||
.idea/replstate.xml | ||
|
||
# Crashlytics plugin (for Android Studio and IntelliJ) | ||
com_crashlytics_export_strings.xml | ||
crashlytics.properties | ||
crashlytics-build.properties | ||
fabric.properties | ||
### C++ template | ||
# Prerequisites | ||
*.d | ||
|
||
# Compiled Object files | ||
*.slo | ||
*.lo | ||
*.o | ||
*.obj | ||
|
||
# Precompiled Headers | ||
*.gch | ||
*.pch | ||
|
||
# Compiled Dynamic libraries | ||
*.so | ||
*.dylib | ||
*.dll | ||
|
||
# Fortran module files | ||
*.mod | ||
*.smod | ||
|
||
# Compiled Static libraries | ||
*.lai | ||
*.la | ||
*.a | ||
*.lib | ||
|
||
# Executables | ||
*.exe | ||
*.out | ||
*.app | ||
### VisualStudioCode template | ||
.vscode/* | ||
!.vscode/settings.json | ||
!.vscode/tasks.json | ||
!.vscode/launch.json | ||
!.vscode/extensions.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
cmake_minimum_required(VERSION 3.8) | ||
project(hopscotch_hashing) | ||
|
||
set(CMAKE_CXX_STANDARD 11) | ||
|
||
set(SOURCE_FILES main.cpp) | ||
add_executable(hopscotch_hashing ${SOURCE_FILES}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
SOURCES = main.cpp | ||
INC_DIR = include | ||
|
||
start: main.cpp | ||
@mkdir -p build | ||
g++ -Wall -std=c++11 -o main $(SOURCES) -I$(INC_DIR) | ||
|
||
run: main | ||
./main | ||
|
||
clean: | ||
rm -rf main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
/* =================================== | ||
* Name: Edgar Sanchez | ||
* Class: Data Structures and Algorithms | ||
* UNT Fall 2017 Programming Assignment 02 | ||
* Hopscotch Hashing | ||
* =================================== */ | ||
#include <iostream> | ||
#include <iomanip> | ||
using namespace std; | ||
|
||
const int TABLE_SIZE = 17; | ||
const int MAX_DIST = 4; | ||
|
||
int insertValue(int); | ||
int deleteValue(int); | ||
int searchValue(int); | ||
void outputTable(); | ||
|
||
void clearKey(int); | ||
int hashValue(int); | ||
|
||
struct Buckets { | ||
bool inUse = false; | ||
int value = 0; | ||
int hop[MAX_DIST] = {0}; | ||
}; | ||
Buckets bucket[TABLE_SIZE]; | ||
|
||
int main() { | ||
int option = 0; | ||
int value = 0; | ||
int key = 0; | ||
|
||
do { | ||
cout << "\nHOPSCOTCH HASHING MENU:\n" | ||
"+------------------------+\n" | ||
"| 1 - Insert Value |\n" | ||
"| 2 - Delete Value |\n" | ||
"| 3 - Search Value |\n" | ||
"| 4 - Output Table |\n" | ||
"| 5 - Exit Program |\n" | ||
"+------------------------+\n\n" | ||
"Enter operation to perform: "; | ||
cin >> option; | ||
cout << endl; | ||
switch ( option ) { | ||
case 1: do { | ||
cout << "Enter positive integer value to insert into Hopscotch Hash Table: "; | ||
cin >> value; | ||
} while (value < 1); | ||
|
||
key = insertValue(value); | ||
if(key >= 0) { | ||
cout << value << " inserted at position " << key << endl; | ||
} else if (key == -1) { | ||
cerr << "ERROR: Unable to insert " << value << " into Hash Table: Hopscotch Hash Failed" << endl; | ||
} else if (key == -2) { | ||
cerr << "ERROR: Unable to insert 16 into Hash Table: Linear Probe Failed" << endl; | ||
} | ||
break; | ||
case 2: do { | ||
cout << "Enter positive integer value to delete from Hopscotch Hash Table: "; | ||
cin >> value; | ||
} while (value < 1); | ||
|
||
key = deleteValue(value); | ||
if(key >= 0) { | ||
cout << value << " deleted from position " << key << "." << endl; | ||
} else { | ||
cerr << "Value not found" << endl; | ||
} | ||
break; | ||
case 3: do { | ||
cout << "Enter positive integer value to search for in Hopscotch Hash Table: "; | ||
cin >> value; | ||
} while (value < 1); | ||
|
||
key = searchValue(value); | ||
if(key >= 0) { | ||
cout << value << " found at position " << key << "." << endl; | ||
} else { | ||
cerr << "Value not found" << endl; | ||
} | ||
break; | ||
case 4: cout << "HOPSCOTCH HASHING TABLE:\n"; | ||
outputTable(); | ||
break; | ||
case 5: cout << "Program terminated by user..." << endl; | ||
break; | ||
default:cerr << "ERROR: Please select operation between 1 and 5, inclusively." << endl; | ||
break; | ||
} | ||
} while (option != 5); | ||
return 0; | ||
} | ||
|
||
// Attempts to insert a value or recursively move values if insertion fails | ||
int insertValue(int value) { | ||
int key = hashValue(value); | ||
|
||
// Inserts a value | ||
// Returns insertion key if successful | ||
// Exits loop if insertion is unsuccessful | ||
for(int i = 0; i < MAX_DIST; ++i) { | ||
if(bucket[key].hop[i] == 0 && !bucket[key + i].inUse) { | ||
key = key + i; | ||
if(key >= TABLE_SIZE) { | ||
// Out of bounds | ||
return -2; | ||
} | ||
|
||
bucket[key - i].hop[i] = 1; | ||
|
||
bucket[key].inUse = true; | ||
bucket[key].value = value; | ||
return key; | ||
} | ||
} | ||
|
||
// Moves a value using recursion | ||
// Returns insertion key if successful | ||
// Exits loop if move is unsuccessful | ||
for(int i = 0; i < MAX_DIST; ++i) { | ||
if(bucket[key].hop[i] == 0) { | ||
int parentKey = hashValue(bucket[key + i].value); | ||
int distance = (key + i) - parentKey; | ||
|
||
for(int j = 0; j < MAX_DIST; ++j) { | ||
if(!bucket[parentKey + j].inUse) { | ||
bucket[parentKey + j].inUse = true; | ||
|
||
bucket[parentKey + j].value = bucket[key + i].value; | ||
|
||
bucket[parentKey].hop[j] = 1; | ||
bucket[parentKey].hop[distance] = 0; | ||
|
||
clearKey(key + i); | ||
insertValue(value); | ||
return key + i; | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Insert and move failed | ||
return -1; | ||
} | ||
|
||
// Deletes a value and returns it's corresponding key | ||
int deleteValue(int value) { | ||
int key = hashValue(value); | ||
|
||
if(bucket[key].hop[0] == 1 && bucket[key].value == value) { | ||
bucket[key].inUse = false; | ||
bucket[key].value = 0; | ||
bucket[key].hop[0] = 0; | ||
return key; | ||
} | ||
else if(bucket[key].hop[1] == 1 && bucket[key + 1].value == value) { | ||
bucket[key + 1].inUse = false; | ||
bucket[key + 1].value = 0; | ||
bucket[key].hop[1] = 0; | ||
return key + 1; | ||
} | ||
else if(bucket[key].hop[2] == 1 && bucket[key + 2].value == value) { | ||
bucket[key + 2].inUse = false; | ||
bucket[key + 2].value = 0; | ||
bucket[key].hop[2] = 0; | ||
return key + 2; | ||
} | ||
else if(bucket[key].hop[3] == 1 && bucket[key + 3].value == value) { | ||
bucket[key + 3].inUse = false; | ||
bucket[key + 3].value = 0; | ||
bucket[key].hop[3] = 0; | ||
return key + 3; | ||
} | ||
else { | ||
// Value not found | ||
return -1; | ||
} | ||
} | ||
|
||
// Clears key field for a corresponding value | ||
void clearKey(int key) { | ||
bucket[key].inUse = false; | ||
bucket[key].value = 0; | ||
bucket[key].hop[0] = 0; //TODO set corresponding parent key to 0 if value doesnt belong | ||
} | ||
|
||
// Searches for a value and returns it's corresponding key | ||
int searchValue(int value) { | ||
int key = hashValue(value); | ||
|
||
if(bucket[key].hop[0] == 1 && bucket[key].value == value) { | ||
return key; | ||
} | ||
else if(bucket[key].hop[1] == 1 && bucket[key + 1].value == value) { | ||
return key + 1; | ||
} | ||
else if(bucket[key].hop[2] == 1 && bucket[key + 2].value == value) { | ||
return key + 2; | ||
} | ||
else if(bucket[key].hop[3] == 1 && bucket[key + 3].value == value) { | ||
return key + 3; | ||
} | ||
else { | ||
// Value not found | ||
return -1; | ||
} | ||
} | ||
|
||
// Prints the current table | ||
void outputTable() { | ||
cout << "+------------------------+\n" | ||
"| # | item | hop |\n" | ||
"+------------------------+\n"; | ||
for(int i = 0; i < TABLE_SIZE; ++i){ | ||
cout << "| " << setw(2) << i << " | " << setw(4) << bucket[i].value << " | " << bucket[i].hop[0] << bucket[i].hop[1] << bucket[i].hop[2] << bucket[i].hop[3] << " |\n"; | ||
} | ||
cout << "+------------------------+" << endl; | ||
} | ||
|
||
// Generates and returns hashValue for a given value | ||
int hashValue(int value) { | ||
return value % TABLE_SIZE; | ||
} |