Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "hash_table.h"
- #include <stdlib.h>
- #include <stdbool.h>
- #include "vector.h"
- #include "../generic/vector_generic.h"
- #define INITIAL_CAPACITY 2
- #define LOAD_FACTOR 0.75 // size/capacity
- #define RESIZE_FACTOR 2
- struct hash_table {
- size_t size;
- size_t capacity;
- vector* table;
- unsigned long (*hash_f)(void*);
- };
- typedef struct hash_entry {
- unsigned long hash;
- hash_value_type type;
- union {
- int i;
- } value;
- } hash_entry;
- static vector_data* create_vector_data() {
- vector_data* data = (vector_data*)malloc(sizeof(vector_data));
- if(data == NULL)
- return NULL;
- data->type = l_list;
- data->value.linked_list = init_linked_list();
- return data;
- }
- static linked_list* get_vector_data(vector_data* data){
- if(data == NULL)
- return NULL;
- if(data->type == l_list)
- return(linked_list*)data->value.linked_list;
- else
- return NULL;
- }
- hash_table* init_hash_table(unsigned long (*hash_f)(void*)) {
- hash_table* hashTbl = (hash_table*)malloc(sizeof(hash_table));
- if(hashTbl == NULL)
- return NULL;
- hashTbl->size = 0;
- hashTbl->capacity = 0;
- size_t cap = INITIAL_CAPACITY;
- hashTbl->table = init_vector_with_init_cap(cap);
- if(hashTbl->table == NULL) {
- free(hashTbl);
- return NULL;
- }
- for(int i = 0; i < cap; i++) {
- if(!add_to_vector(hashTbl->table, create_vector_data())) {
- free_vector(hashTbl->table);
- free(hashTbl);
- return NULL;
- }
- hashTbl->capacity++;
- }
- hashTbl->hash_f = hash_f;
- return hashTbl;
- }
- static bool add_entry(hash_table* hashTbl, hash_entry* entry) {
- size_t index = entry->hash % hashTbl->capacity;
- linked_list* ll = get_vector_data(hashTbl->table->data[index]);
- if(!add_to_list(ll, entry)) {
- return false;
- }
- hashTbl->size++;
- return true;
- }
- static void rehash(hash_table* hashTbl, linked_list* collection) {
- hash_entry* entry = (hash_entry*)pop_from_list(collection);
- while(entry != NULL) {
- add_entry(hashTbl, entry);
- entry = (hash_entry*)pop_from_list(collection);
- }
- }
- static bool resize(hash_table* hashTbl) {
- size_t cap = hashTbl->capacity * RESIZE_FACTOR;
- vector* tmp = init_vector_with_init_cap(cap);
- if(tmp == NULL)
- return false;
- for(int i = 0; i < cap; i++) {
- if(!add_to_vector(tmp, create_vector_data())) {
- free_vector(tmp);
- return false;
- }
- }
- linked_list* collector = init_linked_list();
- for(int i = 0; i < hashTbl->capacity; i++) {
- linked_list* ll = get_vector_data(hashTbl->table->data[i]);
- merge_lists(collector, ll);
- }
- free_vector(hashTbl->table);
- hashTbl->table = tmp;
- hashTbl->capacity *= RESIZE_FACTOR;
- hashTbl->size = 0;
- rehash(hashTbl, collector);
- free_linked_list(collector);
- return true;
- }
- bool bind_to_hash_table(hash_table* hashTbl, void* key, hash_value_type type, void* value) {
- if(((hashTbl->size + 1) / hashTbl->capacity) >= LOAD_FACTOR) {
- if(!resize(hashTbl))
- return false;
- }
- unsigned long hash = hashTbl->hash_f(key);
- hash_entry* entry = (hash_entry*)malloc(sizeof(hash_entry));
- if(entry == NULL)
- return false;
- entry->hash = hash;
- if(type == int_type)
- entry->value.i = *(int*)value;
- entry->type = type;
- return add_entry(hashTbl, entry);
- }
- bool is_binded(hash_table* hashTbl, void* key) {
- unsigned long hash = hashTbl->hash_f(key);
- size_t index = hash % hashTbl->capacity;
- linked_list* ll = get_vector_data(hashTbl->table->data[index]);
- linked_node* node = ll->head;
- while(ll != NULL) {
- hash_entry* e = (hash_entry*)node->data;
- if(e == NULL)
- return false;
- if(e->hash == hash)
- return true;
- node = node->next;
- }
- return false;
- }
- static void* extract_value(hash_entry* entry) {
- if(entry->type == int_type)
- return &entry->value.i;
- return NULL;
- }
- void* get_value(hash_table* hashTbl, void* key) {
- unsigned long hash = hashTbl->hash_f(key);
- size_t index = hash % hashTbl->capacity;
- linked_list* ll = get_vector_data(hashTbl->table->data[index]);
- linked_node* node = ll->head;
- while(ll != NULL) {
- hash_entry* e = (hash_entry*)node->data;
- if(e == NULL)
- return NULL;
- if(e->hash == hash)
- return extract_value(e);
- node = node->next;
- }
- return NULL;
- }
- void free_hash_table(hash_table* hashTbl) {
- if(hashTbl == NULL)
- return;
- free_vector(hashTbl->table);
- free(hashTbl);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement