Advertisement
YaBoiSwayZ

Hash Table (Pretty much dictionary v2)

May 26th, 2024
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.28 KB | Source Code | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <stdbool.h>
  5. #include <string.h>
  6. #include <pthread.h>
  7. #include <time.h>
  8.  
  9. #define INITIAL_NUM_BUCKETS 1024
  10. #define DEFAULT_POOL_SIZE 1024
  11. #define LOAD_FACTOR_THRESHOLD 0.75
  12. #define LENGTH 45
  13.  
  14. typedef struct node {
  15.     char word[LENGTH + 1];
  16.     bool is_deleted;
  17.     struct node *next;
  18.     struct node *free_next;
  19. } node;
  20.  
  21. typedef struct memory_pool {
  22.     node *pool;
  23.     size_t size;
  24.     size_t free_index;
  25.     node *free_list;
  26.     pthread_mutex_t lock;
  27. } memory_pool;
  28.  
  29. typedef struct {
  30.     node **buckets;
  31.     size_t num_buckets;
  32.     size_t word_count;
  33.     pthread_mutex_t lock;
  34.     memory_pool pool;
  35.     double add_word_time;
  36.     double remove_word_time;
  37.     double resize_table_time;
  38. } hash_table;
  39.  
  40. hash_table *table = NULL;
  41.  
  42. bool resize_table();
  43. unsigned int hash(const char *word);
  44. bool initialize_memory_pool(memory_pool *pool, size_t size);
  45. node *allocate_node(memory_pool *pool);
  46. void add_to_free_list(memory_pool *pool, node *n);
  47. bool resize_memory_pool(memory_pool *pool, size_t new_size);
  48. void log_error(const char *message);
  49. void start_timer(clock_t *start);
  50. void stop_timer(clock_t start, double *accumulated_time);
  51.  
  52. unsigned int hash(const char *word) {
  53.     unsigned int hash = 0;
  54.     while (*word) {
  55.         hash = (hash << 2) ^ tolower(*word++);
  56.     }
  57.     return hash;
  58. }
  59.  
  60. bool init_table(size_t initial_pool_size) {
  61.     table = malloc(sizeof(hash_table));
  62.     if (!table) {
  63.         log_error("Failed to allocate hash table.");
  64.         return false;
  65.     }
  66.     table->num_buckets = INITIAL_NUM_BUCKETS;
  67.     table->word_count = 0;
  68.     table->buckets = calloc(table->num_buckets, sizeof(node *));
  69.     if (!table->buckets) {
  70.         free(table);
  71.         log_error("Failed to allocate buckets.");
  72.         return false;
  73.     }
  74.     pthread_mutex_init(&table->lock, NULL);
  75.     if (!initialize_memory_pool(&table->pool, initial_pool_size)) {
  76.         free(table->buckets);
  77.         free(table);
  78.         log_error("Failed to initialize memory pool.");
  79.         return false;
  80.     }
  81.     table->add_word_time = 0.0;
  82.     table->remove_word_time = 0.0;
  83.     table->resize_table_time = 0.0;
  84.     return true;
  85. }
  86.  
  87. bool initialize_memory_pool(memory_pool *pool, size_t size) {
  88.     pool->pool = malloc(size * sizeof(node));
  89.     if (!pool->pool) {
  90.         return false;
  91.     }
  92.     pool->size = size;
  93.     pool->free_index = 0;
  94.     pool->free_list = NULL;
  95.     pthread_mutex_init(&pool->lock, NULL);
  96.     return true;
  97. }
  98.  
  99. node *allocate_node(memory_pool *pool) {
  100.     pthread_mutex_lock(&pool->lock);
  101.     if (pool->free_list) {
  102.         node *n = pool->free_list;
  103.         pool->free_list = n->free_next;
  104.         pthread_mutex_unlock(&pool->lock);
  105.         return n;
  106.     }
  107.     if (pool->free_index >= pool->size) {
  108.         if (!resize_memory_pool(pool, pool->size * 2)) {
  109.             pthread_mutex_unlock(&pool->lock);
  110.             return NULL;
  111.         }
  112.     }
  113.     node *n = &pool->pool[pool->free_index++];
  114.     pthread_mutex_unlock(&pool->lock);
  115.     return n;
  116. }
  117.  
  118. void add_to_free_list(memory_pool *pool, node *n) {
  119.     pthread_mutex_lock(&pool->lock);
  120.     n->free_next = pool->free_list;
  121.     pool->free_list = n;
  122.     pthread_mutex_unlock(&pool->lock);
  123. }
  124.  
  125. bool resize_memory_pool(memory_pool *pool, size_t new_size) {
  126.     node *new_pool = realloc(pool->pool, new_size * sizeof(node));
  127.     if (!new_pool) {
  128.         log_error("Failed to resize memory pool.");
  129.         return false;
  130.     }
  131.     pool->pool = new_pool;
  132.     pool->size = new_size;
  133.     return true;
  134. }
  135.  
  136. bool load(const char *dictionary, size_t initial_pool_size) {
  137.     if (!init_table(initial_pool_size)) {
  138.         return false;
  139.     }
  140.     FILE *file = fopen(dictionary, "r");
  141.     if (file == NULL) {
  142.         unload();
  143.         log_error("Failed to open dictionary file.");
  144.         return false;
  145.     }
  146.     char word[LENGTH + 1];
  147.     while (fscanf(file, "%45s", word) != EOF) {
  148.         if (!add_word(word)) {
  149.             fclose(file);
  150.             unload();
  151.             return false;
  152.         }
  153.     }
  154.     fclose(file);
  155.     return true;
  156. }
  157.  
  158. bool resize_table() {
  159.     size_t new_num_buckets = table->num_buckets * 2;
  160.     node **new_buckets = calloc(new_num_buckets, sizeof(node *));
  161.     if (!new_buckets) {
  162.         log_error("Failed to allocate new buckets for resizing.");
  163.         return false;
  164.     }
  165.     clock_t start;
  166.     start_timer(&start);
  167.     for (size_t i = 0; i < table->num_buckets; i++) {
  168.         node *current = table->buckets[i];
  169.         while (current) {
  170.             node *next = current->next;
  171.             if (!current->is_deleted) {
  172.                 unsigned int new_index = hash(current->word) % new_num_buckets;
  173.                 current->next = new_buckets[new_index];
  174.                 new_buckets[new_index] = current;
  175.             }
  176.             current = next;
  177.         }
  178.     }
  179.     free(table->buckets);
  180.     table->buckets = new_buckets;
  181.     table->num_buckets = new_num_buckets;
  182.     stop_timer(start, &table->resize_table_time);
  183.     return true;
  184. }
  185.  
  186. bool add_word(const char *word) {
  187.     if (!table) return false;
  188.     pthread_mutex_lock(&table->lock);
  189.     if ((double)table->word_count / table->num_buckets > LOAD_FACTOR_THRESHOLD) {
  190.         if (!resize_table()) {
  191.             pthread_mutex_unlock(&table->lock);
  192.             return false;
  193.         }
  194.     }
  195.     clock_t start;
  196.     start_timer(&start);
  197.     unsigned int index = hash(word) % table->num_buckets;
  198.     node *new_node = allocate_node(&table->pool);
  199.     if (!new_node) {
  200.         pthread_mutex_unlock(&table->lock);
  201.         return false;
  202.     }
  203.     strcpy(new_node->word, word);
  204.     new_node->is_deleted = false;
  205.     new_node->next = table->buckets[index];
  206.     table->buckets[index] = new_node;
  207.     table->word_count++;
  208.     stop_timer(start, &table->add_word_time);
  209.     pthread_mutex_unlock(&table->lock);
  210.     return true;
  211. }
  212.  
  213. bool remove_word(const char *word) {
  214.     if (!table) return false;
  215.     pthread_mutex_lock(&table->lock);
  216.     clock_t start;
  217.     start_timer(&start);
  218.     unsigned int index = hash(word) % table->num_buckets;
  219.     node *current = table->buckets[index];
  220.     while (current) {
  221.         if (!current->is_deleted && strcmp(current->word, word) == 0) {
  222.             current->is_deleted = true;
  223.             table->word_count--;
  224.             add_to_free_list(&table->pool, current);
  225.             stop_timer(start, &table->remove_word_time);
  226.             pthread_mutex_unlock(&table->lock);
  227.             return true;
  228.         }
  229.         current = current->next;
  230.     }
  231.     stop_timer(start, &table->remove_word_time);
  232.     pthread_mutex_unlock(&table->lock);
  233.     return false;
  234. }
  235.  
  236. void clean_up_deleted_nodes() {
  237.     pthread_mutex_lock(&table->lock);
  238.     for (size_t i = 0; i < table->num_buckets; i++) {
  239.         node **current = &table->buckets[i];
  240.         while (*current) {
  241.             if ((*current)->is_deleted) {
  242.                 node *temp = *current;
  243.                 *current = (*current)->next;
  244.                 add_to_free_list(&table->pool, temp);
  245.             } else {
  246.                 current = &(*current)->next;
  247.             }
  248.         }
  249.     }
  250.     pthread_mutex_unlock(&table->lock);
  251. }
  252.  
  253. bool unload() {
  254.     if (!table) return false;
  255.     for (size_t i = 0; i < table->num_buckets; i++) {
  256.         node *current = table->buckets[i];
  257.         while (current) {
  258.             node *temp = current;
  259.             current = current->next;
  260.         }
  261.     }
  262.     free(table->buckets);
  263.     free(table->pool.pool);
  264.     pthread_mutex_destroy(&table->lock);
  265.     pthread_mutex_destroy(&table->pool.lock);
  266.     free(table);
  267.     table = NULL;
  268.     return true;
  269. }
  270.  
  271. void log_error(const char *message) {
  272.     fprintf(stderr, "Error: %s\n", message);
  273. }
  274.  
  275. void start_timer(clock_t *start) {
  276.     *start = clock();
  277. }
  278.  
  279. void stop_timer(clock_t start, double *accumulated_time) {
  280.     clock_t end = clock();
  281.     *accumulated_time += ((double)(end - start)) / CLOCKS_PER_SEC;
  282. }
  283.  
  284. int main(int argc, char *argv[]) {
  285.     if (argc != 2) {
  286.         fprintf(stderr, "Usage: %s <dictionary file>\n", argv[0]);
  287.         return 1;
  288.     }
  289.     size_t initial_pool_size = DEFAULT_POOL_SIZE;
  290.     if (!load(argv[1], initial_pool_size)) {
  291.         fprintf(stderr, "Failed to load dictionary.\n");
  292.         return 1;
  293.     }
  294.     add_word("example");
  295.     remove_word("example
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement