#include "../includes/hashtable.h" #include #include #include //Reference https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash //FNV = Fowler–Noll–Vo #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"); } }