Advertisement
cd62131

Build Words Hashtable and Sort

Jul 9th, 2017
352
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.97 KB | None | 0 0
  1. // main.c
  2. #include <stddef.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6. #include "hash.h"
  7.  
  8. int main(void) {
  9.   char *words[] = { "aaa", "baa", "aab", "aba", "bba", "bab", "abb", "bbb", "aaa", "baa", "aab", "aba", "baa", "aab",
  10.       "bbb", "aaa", "baa", "aab", "aba" };
  11.   table *table = table_new();
  12.   for (size_t i = 0; i < sizeof(words) / sizeof(char *); ++i) {
  13.     table_add(table, words[i]);
  14.   }
  15.   puts("hashtable");
  16.   table_print_to(table, stdout);
  17.   node **array = table_entries(table);
  18.   size_t items = table_items(table);
  19.   puts("entries");
  20.   node_array_print_to(array, items, stdout);
  21.   node_array_sort_by_key(array, items);
  22.   puts("sort by key");
  23.   node_array_print_to(array, items, stdout);
  24.   node_array_sort_by_value(array, items);
  25.   puts("sort by value");
  26.   node_array_print_to(array, items, stdout);
  27.   table_delete(table);
  28.   free(array);
  29. }
  30.  
  31. // hash.h
  32. #ifndef HASH_H_
  33. #define HASH_H_
  34.  
  35. #include <stddef.h>
  36. #include <stdio.h>
  37.  
  38. #define HASH_SIZE 997
  39. #define HASH_RADIX 97
  40.  
  41. typedef struct node node;
  42. typedef struct table table;
  43.  
  44. table *table_new(void);
  45. void table_delete(table *);
  46. node *table_has_key(table *, char *);
  47. int table_add(table *, char *);
  48. int table_items(table *);
  49. char **table_keys(table *);
  50. node **table_entries(table *);
  51. void table_print_to(table *, FILE *);
  52. void node_array_print_to(node **, size_t, FILE *);
  53. void node_array_sort_by_key(node **, size_t);
  54. void node_array_sort_by_value(node **, size_t);
  55. int node_key_compare(const void *, const void *);
  56. int node_value_compare(const void *, const void *);
  57.  
  58. #endif /* HASH_H_ */
  59.  
  60. // hash.c
  61. #include "hash.h"
  62.  
  63. #include <assert.h>
  64. #include <stdlib.h>
  65. #include <string.h>
  66.  
  67. struct node {
  68.   char *key;
  69.   int value;
  70.   int id;
  71.   node *next;
  72. };
  73.  
  74. struct table {
  75.   node **head;
  76.   int items;
  77.   int rooms;
  78. };
  79.  
  80. static unsigned int hash(char *);
  81. static int table_index(table *, char *);
  82. static node *node_new(char *);
  83.  
  84. static unsigned int hash(char *str) {
  85.   unsigned int v = 0;
  86.   for (; *str; v = v * HASH_RADIX + *str++)
  87.     ;
  88.   return v;
  89. }
  90.  
  91. static int table_index(table *table, char *key) {
  92.   return hash(key) % table->rooms;
  93. }
  94.  
  95. static node *node_new(char *key) {
  96.   node *new = malloc(sizeof(node));
  97.   new->key = strdup(key);
  98.   new->value = 1;
  99.   new->id = 0;
  100.   new->next = NULL;
  101.   return new;
  102. }
  103.  
  104. table *table_new(void) {
  105.   table *t = malloc(sizeof(table));
  106.   t->items = 0;
  107.   t->rooms = HASH_SIZE;
  108.   t->head = malloc(sizeof(node *) * t->rooms);
  109.   for (size_t i = 0; i < t->rooms; i++) {
  110.     t->head[i] = NULL;
  111.   }
  112.   return t;
  113. }
  114.  
  115. void table_delete(table *table) {
  116.   if (!table) {
  117.     return;
  118.   }
  119.   for (size_t i = 0; i < table->rooms; i++) {
  120.     for (node *p = table->head[i], *q; p; q = p, p = p->next, free(q))
  121.       ;
  122.   }
  123.   free(table->head);
  124.   free(table);
  125. }
  126.  
  127. int table_items(table *table) {
  128.   assert(table);
  129.   return table->items;
  130. }
  131.  
  132. node *table_has_key(table *table, char *key) {
  133.   assert(table && key);
  134.   for (node *n = table->head[table_index(table, key)]; n; n = n->next) {
  135.     if (!strcmp(key, n->key)) {
  136.       return n;
  137.     }
  138.   }
  139.   return NULL;
  140. }
  141.  
  142. int table_add(table *table, char *key) {
  143.   assert(table && key);
  144.   node *found = table_has_key(table, key);
  145.   if (found) {
  146.     found->value++;
  147.     return found->id;
  148.   }
  149.   node *new = node_new(key);
  150.   new->id = table->items++;
  151.   int index = table_index(table, key);
  152.   new->next = table->head[index];
  153.   table->head[index] = new;
  154.   return new->id;
  155. }
  156.  
  157. char **table_keys(table * table) {
  158.   assert(table);
  159.   char **keys = malloc(sizeof(char *) * table->items);
  160.   for (int i = 0; i < table->rooms; ++i) {
  161.     for (node *n = table->head[i]; n; keys[n->id] = n->key, n = n->next)
  162.       ;
  163.   }
  164.   return keys;
  165. }
  166.  
  167. node **table_entries(table *table) {
  168.   assert(table);
  169.   node **array = malloc(sizeof(node *) * table->items);
  170.   for (int i = 0; i < table->rooms; ++i) {
  171.     for (node * n = table->head[i]; n; array[n->id] = n, n = n->next)
  172.       ;
  173.   }
  174.   return array;
  175. }
  176.  
  177. void table_print_to(table *table, FILE *out) {
  178.   assert(table);
  179.   for (int i = 0; i < table->rooms; ++i) {
  180.     for (node *n = table->head[i]; n; fprintf(out, "%s => %d\n", n->key, n->value), n = n->next)
  181.       ;
  182.   }
  183. }
  184.  
  185. void node_array_print_to(node **array, size_t size, FILE *out) {
  186.   for (size_t i = 0; i < size; ++i) {
  187.     fprintf(out, "%s => %d\n", array[i]->key, array[i]->value);
  188.   }
  189. }
  190.  
  191. void node_array_sort_by_key(node **entries, size_t size) {
  192.   qsort(entries, size, sizeof(node *), node_key_compare);
  193. }
  194.  
  195. void node_array_sort_by_value(node **entries, size_t size) {
  196.   qsort(entries, size, sizeof(node *), node_value_compare);
  197. }
  198.  
  199. int node_key_compare(const void *p, const void *q) {
  200.   node *u = *(node **) p;
  201.   node *v = *(node **) q;
  202.   return strcmp(u->key, v->key);
  203. }
  204.  
  205. int node_value_compare(const void *p, const void *q) {
  206.   node *u = *(node **) p;
  207.   node *v = *(node **) q;
  208.   if (u->value < v->value)
  209.     return 1;
  210.   if (u->value > v->value)
  211.     return -1;
  212.   return strcmp(u->key, v->key);
  213. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement