Skip to content

Commit

Permalink
Initial working commit
Browse files Browse the repository at this point in the history
  • Loading branch information
edgariscoding committed Nov 24, 2017
0 parents commit e5dcd94
Show file tree
Hide file tree
Showing 4 changed files with 369 additions and 0 deletions.
124 changes: 124 additions & 0 deletions .gitignore
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
7 changes: 7 additions & 0 deletions CMakeLists.txt
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})
12 changes: 12 additions & 0 deletions Makefile
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
226 changes: 226 additions & 0 deletions main.cpp
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;
}

0 comments on commit e5dcd94

Please sign in to comment.