Implemented a simple hash table using the FNV-1a hashing algorithm. Not drawing routines for it yet, just the bare data structure.

This commit is contained in:
2022-11-03 22:46:00 -05:00
parent 420cf2ac12
commit 33dda8dffe
3 changed files with 138 additions and 0 deletions
+106
View File
@@ -0,0 +1,106 @@
#include "../includes/hashtable.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//Reference https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash
//FNV = FowlerNollVo
#define FNV_OFFSET 0xcbf29ce484222325 //Or 14695981039346656037 in decimal
#define FNV_PRIME 0x100000001b3 //Or 1099511628211 in decimal
#define DEFAULTHASHTABLESIZE 64
Bucket* CreateBucket();
void AddToBucket(char* key, char* text, Bucket* bucket);
HashTable* CreateHashTable(void) {
HashTable* table = calloc(1, sizeof(HashTable));
table->Values = calloc(DEFAULTHASHTABLESIZE, sizeof(Bucket*));
table->Capacity = DEFAULTHASHTABLESIZE;
return table;
}
void AddItemToHashTable(char* key, char* item, HashTable* table) {
//FNV-1a hash
unsigned long long hash = FNV_OFFSET;
for(int i = 0; i < strlen(key); i ++) {
hash ^= key[i];
hash *= FNV_PRIME;
}
unsigned int index = hash % table->Capacity;
Bucket* bucket = table->Values[index];
if (!bucket) table->Values[index] = CreateBucket();
AddToBucket(key, item, table->Values[index]);
}
char* HashTableBucketLinearScan(char* key, Bucket* bucket) {
for(int i = 0; i < bucket->Size; i++) {
BucketKeyPair* pair = bucket->KeyPairs[i];
if (strcmp(key, pair->Key) == 0) return pair->Value;
}
return NULL;
}
char* GetHashTableItem(char* key, HashTable* table) {
unsigned long long hash = FNV_OFFSET;
for(int i = 0; i < strlen(key); i ++) {
hash ^= key[i];
hash *= FNV_PRIME;
}
unsigned int index = hash % table->Capacity;
Bucket* bucket = table->Values[index];
if (!bucket) return NULL;
if (bucket->Size == 1) return bucket->KeyPairs[0]->Value;
return HashTableBucketLinearScan(key, bucket);
}
Bucket* CreateBucket() {
Bucket* bucket = calloc(1, sizeof(Bucket));
bucket->KeyPairs = calloc(16, sizeof(BucketKeyPair*));
bucket->Capacity = 16;
return bucket;
}
void AddToBucket(char* key, char* text, Bucket* bucket) {
BucketKeyPair* keyPair = calloc(1, sizeof(BucketKeyPair));
keyPair->Key = key;
keyPair->Value = text;
bucket->KeyPairs[bucket->Size] = keyPair;
bucket->Size++;
}
void PrintHashTable(HashTable* table) {
printf("Capacity %d\nBuckets:\n", table->Capacity);
for(int i = 0; i < table->Capacity; i++) {
Bucket* bucket = table->Values[i];
if (!bucket) continue;
printf("Bucket %d: \n", i+1);
for(int j = 0; j < bucket->Size; j++) {
printf("(%s) '%s'\n", bucket->KeyPairs[j]->Key, bucket->KeyPairs[j]->Value);
}
printf("\n");
}
}