Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2019
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.45 KB | None | 0 0
  1. #include "hash_table.h"
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. #include "vector.h"
  5. #include "../generic/vector_generic.h"
  6.  
  7. #define INITIAL_CAPACITY 2
  8. #define LOAD_FACTOR 0.75 // size/capacity
  9. #define RESIZE_FACTOR 2
  10.  
  11. struct hash_table {
  12. size_t size;
  13. size_t capacity;
  14.  
  15. vector* table;
  16.  
  17. unsigned long (*hash_f)(void*);
  18. };
  19.  
  20. typedef struct hash_entry {
  21. unsigned long hash;
  22. hash_value_type type;
  23. union {
  24. int i;
  25. } value;
  26. } hash_entry;
  27.  
  28. static vector_data* create_vector_data() {
  29. vector_data* data = (vector_data*)malloc(sizeof(vector_data));
  30. if(data == NULL)
  31. return NULL;
  32.  
  33. data->type = l_list;
  34. data->value.linked_list = init_linked_list();
  35. return data;
  36. }
  37.  
  38. static linked_list* get_vector_data(vector_data* data){
  39. if(data == NULL)
  40. return NULL;
  41. if(data->type == l_list)
  42. return(linked_list*)data->value.linked_list;
  43. else
  44. return NULL;
  45. }
  46.  
  47. hash_table* init_hash_table(unsigned long (*hash_f)(void*)) {
  48. hash_table* hashTbl = (hash_table*)malloc(sizeof(hash_table));
  49. if(hashTbl == NULL)
  50. return NULL;
  51.  
  52. hashTbl->size = 0;
  53. hashTbl->capacity = 0;
  54. size_t cap = INITIAL_CAPACITY;
  55. hashTbl->table = init_vector_with_init_cap(cap);
  56. if(hashTbl->table == NULL) {
  57. free(hashTbl);
  58. return NULL;
  59. }
  60. for(int i = 0; i < cap; i++) {
  61. if(!add_to_vector(hashTbl->table, create_vector_data())) {
  62. free_vector(hashTbl->table);
  63. free(hashTbl);
  64. return NULL;
  65. }
  66. hashTbl->capacity++;
  67. }
  68.  
  69. hashTbl->hash_f = hash_f;
  70. return hashTbl;
  71. }
  72.  
  73.  
  74.  
  75. static bool add_entry(hash_table* hashTbl, hash_entry* entry) {
  76. size_t index = entry->hash % hashTbl->capacity;
  77.  
  78. linked_list* ll = get_vector_data(hashTbl->table->data[index]);
  79. if(!add_to_list(ll, entry)) {
  80. return false;
  81. }
  82.  
  83. hashTbl->size++;
  84. return true;
  85. }
  86.  
  87. static void rehash(hash_table* hashTbl, linked_list* collection) {
  88. hash_entry* entry = (hash_entry*)pop_from_list(collection);
  89.  
  90. while(entry != NULL) {
  91. add_entry(hashTbl, entry);
  92. entry = (hash_entry*)pop_from_list(collection);
  93. }
  94. }
  95.  
  96. static bool resize(hash_table* hashTbl) {
  97. size_t cap = hashTbl->capacity * RESIZE_FACTOR;
  98. vector* tmp = init_vector_with_init_cap(cap);
  99. if(tmp == NULL)
  100. return false;
  101.  
  102. for(int i = 0; i < cap; i++) {
  103. if(!add_to_vector(tmp, create_vector_data())) {
  104. free_vector(tmp);
  105. return false;
  106. }
  107. }
  108.  
  109. linked_list* collector = init_linked_list();
  110.  
  111. for(int i = 0; i < hashTbl->capacity; i++) {
  112. linked_list* ll = get_vector_data(hashTbl->table->data[i]);
  113. merge_lists(collector, ll);
  114. }
  115.  
  116. free_vector(hashTbl->table);
  117. hashTbl->table = tmp;
  118.  
  119. hashTbl->capacity *= RESIZE_FACTOR;
  120. hashTbl->size = 0;
  121. rehash(hashTbl, collector);
  122. free_linked_list(collector);
  123. return true;
  124. }
  125.  
  126. bool bind_to_hash_table(hash_table* hashTbl, void* key, hash_value_type type, void* value) {
  127. if(((hashTbl->size + 1) / hashTbl->capacity) >= LOAD_FACTOR) {
  128. if(!resize(hashTbl))
  129. return false;
  130. }
  131.  
  132. unsigned long hash = hashTbl->hash_f(key);
  133.  
  134. hash_entry* entry = (hash_entry*)malloc(sizeof(hash_entry));
  135. if(entry == NULL)
  136. return false;
  137. entry->hash = hash;
  138. if(type == int_type)
  139. entry->value.i = *(int*)value;
  140.  
  141. entry->type = type;
  142.  
  143. return add_entry(hashTbl, entry);
  144. }
  145.  
  146. bool is_binded(hash_table* hashTbl, void* key) {
  147. unsigned long hash = hashTbl->hash_f(key);
  148. size_t index = hash % hashTbl->capacity;
  149.  
  150. linked_list* ll = get_vector_data(hashTbl->table->data[index]);
  151. linked_node* node = ll->head;
  152. while(ll != NULL) {
  153. hash_entry* e = (hash_entry*)node->data;
  154. if(e == NULL)
  155. return false;
  156. if(e->hash == hash)
  157. return true;
  158. node = node->next;
  159. }
  160. return false;
  161. }
  162.  
  163. static void* extract_value(hash_entry* entry) {
  164. if(entry->type == int_type)
  165. return &entry->value.i;
  166.  
  167. return NULL;
  168. }
  169.  
  170. void* get_value(hash_table* hashTbl, void* key) {
  171. unsigned long hash = hashTbl->hash_f(key);
  172. size_t index = hash % hashTbl->capacity;
  173.  
  174. linked_list* ll = get_vector_data(hashTbl->table->data[index]);
  175. linked_node* node = ll->head;
  176. while(ll != NULL) {
  177. hash_entry* e = (hash_entry*)node->data;
  178. if(e == NULL)
  179. return NULL;
  180. if(e->hash == hash)
  181. return extract_value(e);
  182. node = node->next;
  183. }
  184. return NULL;
  185. }
  186.  
  187. void free_hash_table(hash_table* hashTbl) {
  188. if(hashTbl == NULL)
  189. return;
  190.  
  191. free_vector(hashTbl->table);
  192. free(hashTbl);
  193. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement